给定一个字符串 (sss) 和一个字符模式 (ppp)。实现支持 ‘...’ 和 ‘∗*∗’ 的正则表达式匹配。
‘...’ 匹配任意单个字符。
‘∗*∗’ 匹配零个或多个前面的元素。
匹配应该覆盖整个字符串 (sss) ,而不是部分字符串。
说明:
sss 可能为空,且只包含从 a−za-za−z 的小写字母。
ppp 可能为空,且只包含从 a−za-za−z 的小写字母,以及字符 ... 和 ∗*∗。
示例 111:
输入:s = “aaaaaa”
p = “aaa”
输出: falsefalsefalse
解释: “aaa” 无法匹配 “aaaaaa” 整个字符串。
示例 222:
输入:
sss = “aaaaaa”
ppp = “a∗a*a∗”
输出: truetruetrue
解释: ‘∗*∗’ 代表可匹配零个或多个前面的元素, 即可以匹配 ‘aaa’ 。因此, 重复 ‘aaa’ 一次, 字符串可变为 “aaaaaa”。
示例 333:
输入:
sss = “ababab”
ppp = “.∗.*.∗”
输出: truetruetrue
解释: “.∗.*.∗” 表示可匹配零个或多个(’∗*∗’)任意字符(’...’)。
示例 444:
输入:
sss = “aabaabaab”
ppp = “c∗a∗bc*a*bc∗a∗b”
输出: truetruetrue
解释: ‘ccc’ 可以不被重复, ‘aaa’ 可以被重复一次。因此可以匹配字符串 “aabaabaab”。
示例 555:
输入:
sss = “mississippimississippimississippi”
ppp = “mis∗is∗p∗.mis*is*p*.mis∗is∗p∗.”
输出: falsefalsefalse
思路:
1)递归。
- 如果ppp的下一个字符为∗*∗,那么(1)(1)(1)当sss不为空且p[0]=s[0]p[0] = s[0]p[0]=s[0]或p[0]=′.′p[0] = '.'p[0]=′.′,即该位能够匹配时,那么这个时候由于∗*∗可以匹配多个前面字符,则递归描述为(s+1,p)(s + 1, p)(s+1,p),在这里采取截取字符串的方式,(s.substr(1),p)(s.substr(1), p)(s.substr(1),p) (2)(2)(2)当不满足(1)(1)(1)条件时,则递归描述为(s,p.substr(2))(s, p.substr(2))(s,p.substr(2))
- 如果ppp的下一个字符不为∗*∗,那么只有两个字符匹配,即sss不为空且p[0]=s[0]p[0] = s[0]p[0]=s[0]或p[0]=′.′p[0] = '.'p[0]=′.′成立时,才能继续匹配下一个字符,递归描述为(s.substr(1),p.substr(1))(s.substr(1), p.substr(1))(s.substr(1),p.substr(1))
class Solution {
public:
bool isMatch(string s, string p) {
if (p.empty()) return s.empty();
if (p.size() > 1 && p[1] == '*') {
//两种匹配方式
return isMatch(s, p.substr(2)) ||
(!s.empty() && (s[0] == p[0] || p[0] == '.')
&& isMatch(s.substr(1), p));
} else {
//满足前面条件才能继续匹配
return !s.empty() && (s[0] == p[0] ||
p[0] == '.') && isMatch(s.substr(1), p.substr(1));
}
}
};
2)动态规划。实则对上述递归表达的解析。
- dp[i][j]=truedp[i][j] = truedp[i][j]=true描述为sss中前iii个字符与ppp中前jjj个字符匹配
- 如果p[j−1]=′∗′p[j - 1] = '*'p[j−1]=′∗′,那么对应上述的第1)1)1)种情况,则有dp[i][j]=dp[i][j−2]dp[i][j] = dp[i][j - 2]dp[i][j]=dp[i][j−2] || (i>0i > 0i>0 && (s[i−1]==p[j−2]∣∣p[j−2]==′.′s[i - 1] == p[j - 2] || p[j - 2] == '.'s[i−1]==p[j−2]∣∣p[j−2]==′.′ ) && dp[i−1][j]dp[i - 1][j]dp[i−1][j],即将上述的分析逆转一下
- 如果p[j - 1] != ‘*’,那么对应上述的第2)种情况,则有$dp[i][j] = i > 0 && dp[i - 1][j - 1] && (s[i - 1] == p[j - 1] || p[j - 1] == '.
class Solution {
public:
bool isMatch(string s, string p) {
int m = s.size(), n = p.size();
bool dp[m + 1][n + 1];
memset(dp, false, sizeof(dp));
dp[0][0] = true;
for (int i = 0; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (j > 1 && 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[m][n];
}
};