(一)递归方法
具体参考:https://blog.csdn.net/qq_28410301/article/details/100182901
对于匹配的p字符串有三种情况:
①c=‘.’ ; 可以匹配任何一个字符
②c=‘*’;在一个字符后边,表示可以重复0-n次这个字符
③c=普通字符
第一种和第三种情况都很好处理,重要的是第二种情况。
第二种情况分为:
①匹配前面的字符0次,将这个字符和*一起跳过,继续调用isMatch()
②匹配前面的字符多次。比较首元素,如果相同,s的元素+1,保持p不变继续调用isMatch()
p空:如果s空,返回true;如果s不空,返回false
p不空:①第二个元素是’‘,isMatch(s,p.substr(2))(重复字符匹配0次);
②p第一个元素和s串里的第一个元素匹配并且p的第二个元素是’',isMatch(s.substr(1),p)(跳过s第一个元素,继续进行剩下元素的匹配)
③如果第二个元素不是‘*’,进行正常顺序匹配,并且isMatch(s.substr(1),s.substr(1))进行接下来的匹配
class Solution {
public:
bool isMatch(string s, string p) {
// 在p为空后 只需要查看s是否为空即可
if (p.empty()) {
return s.empty();
}
// 查看首元素是否一致
bool first_match = !s.empty() && (s[0] == p[0] || p[0] == '.');
// 如果下一个字符是'*'
if (p.size() >= 2 && p[1] == '*') {
return (bool)( isMatch(s, p.substr(2)) || (first_match && isMatch(s.substr(1), p)));
}
// 一般情况
else {
return bool( first_match && isMatch(s.substr(1), p.substr(1)));
}
}
};
(二)动态规划
每一次匹配都是基于之前的匹配结果,所以可以自然的想到动态规划的开始是两个空串可以相互匹配,所以搭建dp[i][j]的二维数组并且dp[0][0]为true。
class Solution {
public:
bool isMatch(string s, string p) {
int n = s.size(), m = p.size(); //dp[i][j]表示s[0...i)与p[0...j)是否匹配
vector<vector<bool>> dp(n + 1, vector<bool>(m + 1, false));
dp[0][0] = true; //表示s[0,0)与p[0,0)匹配
for (int i = 1; i <= n; ++i) dp[i][0] = false; //表示s[0,i)与p[0,0)不匹配
for (int i = 1; i <= m; ++i) {
if (p[i - 1] != '*') dp[0][i] = false; //表示s[0,0)与p[0,i)不匹配
else dp[0][i] = dp[0][i - 2]; //表示s[0,0)与p[0,i)匹配结果,由s[0,0)与p[0,i-2)匹配的结果决定
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (s[i - 1] == p[j - 1] || p[j - 1] == '.') dp[i][j] = dp[i - 1][j - 1]; //此处匹配
else if (p[j - 1] == '*') //字符匹配且s[0,i-1)与p[0,j)匹配(匹配1次到多次) 或 s[0,i)与p[0,j-2)匹配(匹配0次)
dp[i][j] = (((s[i - 1] == p[j - 2] || p[j - 2] == '.' ) && dp[i - 1][j]) || dp[i][j - 2]);
else dp[i][j] = false;
}
}
return dp[n][m];
}
};