题目链接:Regular Expression Matching
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).
The function prototype should be:
bool isMatch(const char *s, const char *p)
Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true
这道题的要求是判断字符串s能否和正则表达式p相匹配。其中‘.‘匹配任意单个字符,‘*‘匹配0个或多个‘*‘的前一字符。如果匹配能整个串返回true。
1. 回溯暴力匹配
思路是进行递归回溯匹配。当p的下一个字符是‘*‘的时候,则循环检测p与s的当前字符是否匹配(每次s后移1位,直到结束或者不匹配);当p的下一个字符不是‘*‘的时候,直接检测字符串是否结束或者p与s的当前字符是否匹配。注意‘.‘可以与任意单个字符匹配。
时间复杂度:???
空间复杂度:O(1)
1 class Solution
2 {
3 public:
4 bool isMatch(const char *s, const char *p)
5 {
6 if(*p == ‘\0‘ )
7 return *s == ‘\0‘;
8
9 if(*(p + 1) == ‘*‘)
10 {
11 while(*s != ‘\0‘ && (*p == ‘.‘ || *s == *p))
12 {
13 if(isMatch(s, p + 2))
14 return true;
15 ++ s;
16 }
17 return isMatch(s, p + 2);
18 }
19 else if(*s != ‘\0‘ && (*p == ‘.‘ || *s == *p))
20 return isMatch(s + 1, p + 1);
21
22 return false;
23 }
24 };
2. 动态规划
思路是使用bool类型的二维数组dp[m+1][n+1](m、n分别为字符串s和p的长度)记录s和p是否匹配,即dp[i+1][j+1]表示s的前i个字符是否与p的前j的字符相匹配。
如果p[j]不等于‘*‘,则dp[i + 1][j + 1] = dp[i][j] && s[i] == p[j]
如果p[j]等于‘*‘,则当且仅当在下面三种情况为真,dp[i + 1][j + 1]为真:
-
‘*‘前面字符重复出现0次,则p字符串需要往前看2位,即dp[i + 1][j - 1]是否为真
-
‘*‘前面的字符重复出现1次,则p字符串只需要往前看1位,即dp[i + 1][j]是否为真
-
‘*‘前面的字符重复出现次数大于1次,则s字符串需要往前看1位,即dp[i][j + 1]是否为真,以及s字符串当前字符(s[i])与p字符串‘*‘前面字符(p[j - 1])是否相匹配。
注意,‘.‘可以与任意单个字符匹配。
注:动态规划思路是参考的这里。这里将空间复杂度降低到了O(n),有兴趣的可以看看。
时间复杂度:O(mn)
空间复杂度:O(mn)
1 class Solution
2 {
3 public:
4 bool isMatch(const char *s, const char *p)
5 {
6 int m = strlen(s), n = strlen(p);
7 bool dp[m + 1][n + 1];
8
9 dp[0][0] = true;
10 for(int i = 0; i < m; ++ i)
11 dp[i + 1][0] = false;
12 for(int j = 0; j < n; ++ j)
13 dp[0][j + 1] = ‘*‘ == p[j] && dp[0][j - 1];
14
15 for(int i = 0; i < m; ++ i)
16 for(int j = 0; j < n; ++ j)
17 {
18 if(p[j] != ‘*‘)
19 dp[i + 1][j + 1] = dp[i][j] && (‘.‘ == p[j] || s[i] == p[j]);
20 else
21 dp[i + 1][j + 1] = dp[i + 1][j - 1] || dp[i + 1][j] ||
22 dp[i][j + 1] && (‘.‘ == p[j - 1] || s[i] == p[j - 1]);
23 }
24
25 return dp[m][n];
26 }
27 };