|
2 | 2 | pub(crate) struct Solution;
|
3 | 3 |
|
4 | 4 | enum Token {
|
5 |
| - Char(u8), |
| 5 | + Char(char), |
6 | 6 | Star(Box<Token>),
|
7 | 7 | Dot
|
8 | 8 | }
|
9 | 9 |
|
10 |
| -#[derive(Clone)] |
11 |
| -enum Match { |
12 |
| - None, |
13 |
| - One(usize), |
14 |
| - Star(StarMatch) |
15 |
| -} |
16 |
| - |
17 |
| -#[derive(Clone)] |
18 |
| -struct StarMatch { |
19 |
| - index:usize, |
20 |
| - length:usize, |
| 10 | +impl Token { |
| 11 | + fn consumes(&self, c:&char) -> bool { |
| 12 | + match self { |
| 13 | + Token::Char(tc) => *tc == *c, |
| 14 | + Token::Star(t) => t.consumes(c), |
| 15 | + Token::Dot => true |
| 16 | + } |
| 17 | + } |
21 | 18 | }
|
22 | 19 |
|
23 | 20 | impl Solution {
|
24 | 21 | pub fn is_match(s: String, p: String) -> bool {
|
25 |
| - let chars = s.as_bytes(); |
| 22 | + let chars:Vec<char> = s.chars().collect(); |
26 | 23 | let pattern = Solution::parse_pattern(p);
|
27 |
| - let mut matches = vec![Match::None; pattern.len()]; |
28 |
| - |
29 |
| - let mut token_i = 0; |
30 |
| - let mut char_i = 0; |
31 |
| - loop { |
32 |
| - matches[token_i] = match &pattern[token_i] { |
33 |
| - Token::Char(c) if c == chars[char_i] => unimplemented!(), |
34 |
| - Token::Star(t) => unimplemented!(), |
35 |
| - Token::Dot => unimplemented!(), |
36 |
| - } |
37 |
| - } |
38 | 24 |
|
39 |
| - unimplemented!() |
| 25 | + Solution::matches(pattern.as_slice(), chars.as_slice()) |
40 | 26 | }
|
41 | 27 |
|
42 |
| - fn char(c: &char, i: &mut usize, chars: &Vec<char>) -> bool { |
43 |
| - if chars[*i] == *c { |
44 |
| - *i += 1; |
45 |
| - true |
46 |
| - } else { |
47 |
| - false |
48 |
| - } |
49 |
| - } |
50 | 28 |
|
51 |
| - fn dot(i: &mut usize) -> bool { |
52 |
| - *i += 1; |
53 |
| - true |
| 29 | + fn matches(pattern: &[Token], chars: &[char]) -> bool { |
| 30 | + for (i,t) in pattern.iter().enumerate() { |
| 31 | + if let Token::Star(t) = t { |
| 32 | + let mut ii = i; |
| 33 | + if Solution::matches(&pattern[i + 1..], &chars[ii..]){ |
| 34 | + return true; |
| 35 | + } |
| 36 | + while ii < chars.len() && t.consumes(&chars[ii]) { |
| 37 | + if Solution::matches(&pattern[i + 1..], &chars[ii+1..]){ |
| 38 | + return true; |
| 39 | + } |
| 40 | + ii+=1; |
| 41 | + } |
| 42 | + return false; |
| 43 | + } else if i>= chars.len() || !t.consumes(&chars[i]) { |
| 44 | + return false; |
| 45 | + } |
| 46 | + } |
| 47 | + pattern.len() == chars.len() |
54 | 48 | }
|
55 | 49 |
|
56 |
| - // fn matcher(t: &Token, i: &mut usize, chars: &Vec<char>) -> Match { |
57 |
| - // match t { |
58 |
| - // Token::Char(c) => if *i >= chars.len() || !Solution::char(c, i, chars) { return false; } |
59 |
| - // Token::Dot => if *i >= chars.len() || !Solution::dot(i) { return false; } |
60 |
| - // Token::Star(t) => { |
61 |
| - // //TODO make less greedy |
62 |
| - // while Solution::matcher(t, i, chars) {} |
63 |
| - // } |
64 |
| - // } |
65 |
| - // return true |
66 |
| - // } |
67 |
| - |
68 | 50 |
|
69 |
| - fn parse_pattern<'a>(p: String) -> Vec<Token> { |
| 51 | + fn parse_pattern(p: String) -> Vec<Token> { |
70 | 52 | let mut pattern: Vec<Token> = Vec::with_capacity(p.len());
|
71 | 53 |
|
72 | 54 | for c in p.chars() {
|
|
0 commit comments