Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'.

'.' Matches any single character.
'*' Matches zero or more of the preceding element.

The matching should cover the entire input string (not partial).

Note:

  • s could be empty and contains only lowercase letters a-z.
  • p could be empty and contains only lowercase letters a-z, and characters like . or *

 

分析

模拟简单的正则匹配。'.'代表任意字符,'*'表示把前一个字符重复任意次(包括0次)。

比较麻烦的是这个'*'号,没有这个符号就很简单了,只要从头到尾比较就可以了。所以在第二个字符是'*'时,需要进行特殊处理。

最复杂的情况是,第二个字符是'*',且第一个字符还匹配。这时既要考虑到底是用第一个字符来匹配还是用后面的字符匹配。

就是说,要考虑下面两种情况:

1. s = "a" p = 'a*a'

2. s = "a" p = 'a*'

这两个case都应该匹配才对。

 

 1 public class Solution {
 2     public bool IsMatch(string s, string p)
 3     {
 4         if (string.IsNullOrEmpty(p))
 5         {
 6             return string.IsNullOrEmpty(s);
 7         }
 8         
 9         if (!string.IsNullOrEmpty(s) && (s[0] == p[0] || p[0] == '.'))
10         {
11             if (p.Length > 1 && p[1] == '*')
12             {
13                 return IsMatch(s.Substring(1), p) || IsMatch(s, p.Substring(2));
14             }
15             else
16             {
17                 return IsMatch(s.Substring(1), p.Substring(1));
18             }
19         }
20         else
21         {
22             if (p.Length > 1 && p[1] == '*')
23             {
24                 return IsMatch(s, p.Substring(2));
25             }
26             else
27             {
28                 return false;
29             }
30         }
31     }
32 }

 

PS. 因为字符串截取开销比较大,所以现在这个代码用时比较久,优化的方法是维护两个指针去遍历字符串,并缓存结果。但总体思路是一致的,就不再写了。

PPS. 题目中没提到表达式第一个就是'*'或者连续'*'的情况,这里也就没考虑直接submit试试,居然直接通过了。

后来自己写case发现跟答案是有出入的。看来实际的用例中是没有这种非法的输入值。果然像leetcode这样做得挺不错的题库也有一些考虑不到的情况。

不过我也就是写着玩玩不必较真啦:)