dp:
class Solution {
public:
bool isMatch(string s, string p) {
//tag 用于dp,tag[i][j]代表s的子串s[0,i-1] 可以匹配 p的子串p[0,j-1]。
bool ** tag = new bool*[s.length() + 1];
for (int i = 0; i <= s.length(); i ++){
tag[i] = new bool [p.length() + 1];
memset(tag[i], 0, sizeof(bool) * (p.length() + 1));
}
//tag[0][0]初始化条件,可以理解成,s和p的子串s[0,-1], p[0,-1]匹配,即两个空串匹配。
tag[0][0] = true;
//dp的递推方程是:tag[i][j] =
// (1)p[j - 1] == '*', 则为:tag[i - 1][j - 1] || tag[i][j - 1] || tag[i - 1][j];
// (2)为:tag[i - 1][j - 1] && (p[j - 1] == '?' ? 1: p[j - 1] == s[i - 1])
for (int j = 1; j <= p.length(); j ++){
for (int i = 0; i <= s.length(); i ++){
if (p[j - 1] == '*'){
tag[i][j] = (i > 0 ? (tag[i - 1][j - 1]||tag[i - 1][j]): 0) || tag[i][j - 1];
}
else if (i != 0){
tag[i][j] = tag[i - 1][j - 1] && (p[j - 1] == '?' ? 1: p[j - 1] == s[i - 1]);
}
}
}
return tag[s.length()][p.length()];
}
};
带回溯的贪心:
思路是*字符匹配的时候,可以匹配0~无穷多个字符。所以,枚举s串被匹配的字符数量。
方法是匹配到*的时候,记录下s和p的位置s*和p*,给p的位置+1, s位置不变,此时*匹配0个字符,然后s和p继续匹配之后的字符串。如果匹配不成功,回溯,p的匹配位置更改回p*+1,s的位置更改为记录s*+1,此时*匹配1个字符,然后s和p继续匹配之后的字符。依此类推。
class Solution {
public:
bool isMatch(string s, string p) {
int scur = 0, pcur = 0, sstar = -1, pstar = -1;
while(scur != s.length()){
if (s[scur] == p[pcur] || p[pcur] == '?'){
scur ++; pcur ++;
}
else if (p[pcur] == '*'){
pstar = pcur ++;
sstar = scur;
}
else if (pstar != -1){
pcur = pstar + 1;
scur = ++ sstar;
}
else{
return false;
}
}
while (p[pcur] == '*'){
pcur ++;
}
return pcur == p.length();
}
};