leetcode_rust/problems_cn/p000_0xx/
p000_010.rs1use std::collections::HashMap;
47
48pub fn is_match(s: String, p: String) -> bool {
54 alg_1(s, p)
55 }
58
59#[derive(Debug)]
61struct MatchRuleNode {
62 allow_empty: bool, allow_repeat: bool, allow_any: bool, u8: u8,
66}
67
68#[derive(Debug)]
72struct MatchTree {
73 labeled_results: HashMap<(usize, usize), bool>,
74}
75impl MatchTree {
76 fn match_next(&mut self, s: &[u8], nodes: &[MatchRuleNode]) -> bool {
84 macro_rules! label_pair {
85 ($s:expr, $p:expr) => {{
86 if !self.labeled_results.contains_key(&($s, $p)) {
87 self.labeled_results.insert(($s, $p), false);
88 }
89 false
90 }};
91 }
92
93 macro_rules! match_if_not_labeled {
94 ($s:expr, $n:expr) => {
95 if self.labeled_results.contains_key(&($s.len(), $n.len())) {
96 *self.labeled_results.get(&($s.len(), $n.len())).unwrap()
97 } else {
98 self.match_next($s, $n)
99 }
100 };
101 }
102
103 if nodes.len() == 0 && s.len() > 0 {
104 label_pair!(s.len(), nodes.len())
105 } else if s.len() == 0 && nodes.len() > 0 {
106 for n in nodes {
107 if !n.allow_empty {
108 return label_pair!(s.len(), nodes.len());
109 }
110 }
111 true
112 } else if s.len() == 0 && nodes.len() == 0 {
113 true
114 } else {
115 if nodes.len() == 1 && !nodes[0].allow_any {
116 for ch in s {
118 if *ch != nodes[0].u8 {
119 return label_pair!(s.len(), nodes.len());
120 }
121 }
122 }
123
124 if nodes[0].allow_any {
125 if nodes[0].allow_repeat {
126 match_if_not_labeled!(&s[1..], &nodes[1..])
127 || match_if_not_labeled!(s, &nodes[1..])
128 || match_if_not_labeled!(&s[1..], nodes)
129 } else {
130 match_if_not_labeled!(&s[1..], &nodes[1..])
131 }
132 } else if nodes[0].u8 == s[0] {
133 if nodes[0].allow_repeat {
134 match_if_not_labeled!(&s[1..], &nodes[1..])
135 || match_if_not_labeled!(s, &nodes[1..])
136 || match_if_not_labeled!(&s[1..], nodes)
137 } else {
138 match_if_not_labeled!(&s[1..], &nodes[1..])
139 }
140 } else if nodes[0].allow_empty {
141 match_if_not_labeled!(s, &nodes[1..])
142 } else {
143 label_pair!(s.len(), nodes.len())
144 }
145 }
146 }
147}
148
149fn parse_pattern(p: &str) -> Vec<MatchRuleNode> {
156 let mut nodes = vec![];
157
158 let mut idx = 0;
159 let pbytes = p.as_bytes();
160 loop {
161 if idx == pbytes.len() {
162 break;
163 }
164 let mut temp_node = MatchRuleNode {
165 allow_empty: true,
166 allow_repeat: true,
167 allow_any: pbytes[idx] == 46,
168 u8: pbytes[idx],
169 };
170 if pbytes.len() - 1 > idx && pbytes[idx + 1] == 42 {
171 idx += 2;
172 } else {
173 temp_node.allow_empty = false;
174 temp_node.allow_repeat = false;
175 idx += 1;
176 }
177 if nodes.len() > 0 {
178 let last: &MatchRuleNode = nodes.last().unwrap();
179 if last.u8 == temp_node.u8
180 && temp_node.allow_repeat == true
181 && last.allow_any == temp_node.allow_any
182 && last.allow_repeat == temp_node.allow_repeat
183 && last.allow_empty == temp_node.allow_empty
184 {
185 continue;
187 }
188 }
189 nodes.push(temp_node);
190 }
191
192 nodes
193}
194
195#[allow(unused)]
201fn alg_1(s: String, p: String) -> bool {
202 let mut nodes = parse_pattern(p.as_str());
203 let mut tree = MatchTree {
204 labeled_results: HashMap::new(),
205 };
206
207 tree.match_next(&s.as_bytes(), nodes.as_slice())
208}
209
210#[deprecated(
216 since = "0.2.1",
217 note = "此方法会导致 \"Time Limit Exceeded\" 错误"
218)]
219#[allow(unused)]
220fn alg_2(s: String, p: String) -> bool {
221 let mut match_tree: Vec<(bool, bool, bool, u8)> = vec![];
222
223 let mut idx = 0;
224 let pbytes = p.as_bytes();
225 loop {
226 if idx == pbytes.len() {
227 break;
228 }
229 let mut temp_node = (true, true, pbytes[idx] == 46, pbytes[idx]);
230 if pbytes.len() - 1 > idx && pbytes[idx + 1] == 42 {
231 idx += 2;
232 } else {
233 temp_node.0 = false;
234 temp_node.1 = false;
235 idx += 1;
236 }
237 if match_tree.len() > 1 {
238 let last = match_tree.last().unwrap();
239 if last.3 == temp_node.3
240 && temp_node.1 == true
241 && last.2 == temp_node.2
242 && last.1 == temp_node.1
243 && last.0 == temp_node.0
244 {
245 continue;
247 }
248 }
249 match_tree.push(temp_node);
250 }
251
252 fn recur(s: &[u8], nodes: &[(bool, bool, bool, u8)]) -> bool {
253 if nodes.len() == 0 && s.len() > 0 {
254 false
255 } else if s.len() == 0 && nodes.len() > 0 {
256 for n in nodes {
257 if !n.0 {
258 return false;
259 }
260 }
261 true
262 } else if s.len() == 0 && nodes.len() == 0 {
263 true
264 } else {
265 if nodes[0].2 {
266 if nodes[0].1 {
267 recur(&s[1..], nodes) || recur(&s[1..], &nodes[1..]) || recur(s, &nodes[1..])
268 } else {
269 recur(&s[1..], &nodes[1..])
270 }
271 } else if nodes[0].3 == s[0] {
272 if nodes[0].1 {
273 recur(&s[1..], nodes) || recur(&s[1..], &nodes[1..]) || recur(s, &nodes[1..])
274 } else {
275 recur(&s[1..], &nodes[1..])
276 }
277 } else if nodes[0].0 {
278 recur(s, &nodes[1..])
279 } else {
280 false
281 }
282 }
283 }
284
285 recur(s.as_bytes(), &match_tree)
286}
287
288struct State {
291 ch: u8,
292 wildcard: bool,
293}
294
295#[allow(unused)]
303fn alg_3_from_leetcode(s: String, p: String) -> bool {
304 let states: Vec<State> = p
305 .bytes()
306 .enumerate()
307 .filter_map(|(i, ch)| {
308 if ch == b'*' {
309 None
310 } else {
311 Some(State {
312 ch,
313 wildcard: p.as_bytes().get(i + 1).copied() == Some(b'*'),
314 })
315 }
316 })
317 .chain([State {
318 ch: 0,
319 wildcard: false,
320 }])
321 .collect();
322 let state_count = states.len();
323
324 let mut cur_states = vec![false; state_count];
325 let add_state = |dest: &mut Vec<bool>, mut i: usize| {
326 while !dest[i] {
327 dest[i] = true;
328 if states[i].wildcard {
329 i += 1;
330 } else {
331 break;
332 }
333 }
334 };
335
336 add_state(&mut cur_states, 0);
338
339 for ch in s.into_bytes() {
341 if cur_states.is_empty() {
342 break;
343 }
344 let mut new_states = vec![false; state_count];
345 for i in 0..state_count {
346 if cur_states[i] && (states[i].ch == b'.' || states[i].ch == ch) {
347 if states[i].wildcard {
348 add_state(&mut new_states, i);
349 } else {
350 add_state(&mut new_states, i + 1);
351 }
352 }
353 }
354 cur_states = new_states;
355 }
356
357 cur_states.last().copied().unwrap_or(false)
358}