动态规划
dp[i][j]
表示s的前i个字符与p的前j个字符是否匹配。
bool isMatch(string s, string p) {
size_t m = s.size(), n = p.size();
vector<vector<bool>> dp(m + 1, vector<bool>(n + 1, false));
dp[0][0] = true;
//初始化,p的前j个字符与空字符串匹配,只有当p的前面为*时,才能匹配
for (size_t j = 1; j <= n; ++j)
if (p[j - 1] == '*')
dp[0][j] = dp[0][j - 1];
//至于dp[i][0]表示空字符模式与字符串s匹配,显然是不能匹配的,因此都是false,不需要再额外处理
for (size_t i = 1; i <= m; ++i)
for (size_t j = 1; j <= n; ++j)
//如果最后一个字符匹配,或者模式的最后一个字符为?
if (s[i - 1] == p[j - 1] || p[j - 1] == '?')
dp[i][j] = dp[i - 1][j - 1];
//模式的最后一个字符为*,则*可以匹配0个字符(dp[i][j - 1]),也可以匹配多个字符(dp[i - 1][j])
//虽然dp[i - 1][j]表面上是只匹配了一个字符,
//但是dp[i-1][j] = dp[i - 2][j] || dp[i-1][j - 1];可以多层嵌套以表示匹配多个字符
else if (p[j - 1] == '*')
dp[i][j] = dp[i - 1][j] || dp[i][j - 1];
return dp[m][n];
}
双指针
bool isMatch(string s, string p) {
size_t i=0,j=0,start_s=-1,start_p=-1;
while(i<s.size()){
//匹配后,两个指针都往后移
if(j<p.size() && (s[i]==p[j] || p[j]=='?')){
++i;
++j;
//有*,则记录下两个指针的位置,暂且让*匹配空字符(++j)
}else if(j<p.size() && p[j]=='*'){
start_p = j;
start_s = i;
++j;
//如果不匹配也不是*,而且之前有*(start_p存的就是*的位置),则j回到*的后面,i回到start_s的后面(表示让*多匹配一个字符)
}else if(start_p != -1){
j = start_p + 1;
i = ++start_s;
}else{
//字符不匹配也没有*,返回
return false;
}
}
//将末尾多余的*匹配空字符
while(j<p.size() && p[j]=='*')
++j;
return j == p.size();
}