Leetcode: 10. Regular Expression Matching
Description
Implement regular expression matching with support for '.' and '*'.
Example
'.' 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
思路
- 匹配问题
- '.' 匹配任意单个字符,'*' 匹配前面的字符0次或多次
- 因为需要考虑前面的字符,所以从后往前匹配。
- 考虑 '*'时的特殊情况,如果 ' * '前面的字符和要匹配的一样,则分两张情况,即匹配0次或多次
- 如果不一样,则要匹配的不变,然后跳到*字符前面的前面。
- 没有说清楚,看代码吧
代码
class Solution {
public:
bool isMatch(string s, string p) {
int slen = s.size();
int plen = p.size();
return matchFunc(s, slen - 1, p, plen - 1);
}
bool matchFunc(string& s, int i, string &p, int j){
if(i < 0 && j < 0) return true;
if(i < 0 ) return p[j] == '*' ? matchFunc(s, i, p, j - 2) : false;
if(j < 0) return false;
if(s[i] == p[j] || p[j] == '.'){
return matchFunc(s, i - 1, p, j - 1);
}
else if(p[j] == '*'){
bool res = false;
//特殊情况
if(j - 1 >= 0){
if(p[j - 1] == '.' || p[j - 1] == s[i])
res = matchFunc(s, i - 1, p, j) || matchFunc(s, i - 1, p, j - 2);
}
return res || matchFunc(s, i, p, j - 2);
}
return false;
}
};
动态规划
-
再讨论区里面还看到了一种动态规划的算法。在这里也作一个介绍,不得不感叹一句,大佬还是多呀。
-
dp[i][j] 表示s[0..i)和p[0..j)的匹配结果,若为ture,则匹配,否则不匹配
-
则一共有以下状态:
- dp[i][j] = dp[i - 1][j - 1],if p[j - 1] != '*' && (s[i - 1] == p[j - 1] || p[j - 1] == '.'),注意下标的控制,dp[i][j]的下标是长度,而p[j-1]对应于dp[i][j]
- dp[i][j] = dp[i][j - 2], if p[j - 1] == '*', 且匹配0次
- dp[i][j] = dp[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == '.'),此时p[j - 1] == '*' 且至少匹配一次
-
代码如下:
class Solution { public: bool isMatch(string s, string p) { int slen = s.size(); int plen = p.size(); vector<vector<bool>> dp(slen + 1, vector<bool>(plen + 1, false)); dp[0][0] = true; for(int i = 0; i <= slen; ++i){ for(int j = 1; j <= plen; ++j){ if(p[j - 1] == '*'){ dp[i][j] = dp[i][j - 2] || (i > 0 && (s[i - 1] == p[j - 2] || p[j - 2] == '.') && dp[i - 1][j]); } else dp[i][j] = i > 0 && dp[i - 1][j - 1] && (s[i - 1] == p[j - 1] || p[j - 1] == '.'); } } return dp[slen][plen]; } };
总结
- 递归往往可以改善的
- 向大佬学习!