44. Wildcard Matching
又是一道通配符的问题,和:https://blog.csdn.net/weixin_43462819/article/details/100878953 很像,但是有一个关键的思路还是没能够灵活运用,导致没有做出最优的解法。
首先是自己的解法:
class Solution {
public:
bool isMatch(string s, string p) {
int ssz = s.size(), psz = p.size();
vector<vector<bool>> dp(ssz+1, vector<bool>(psz+1, false));
dp[0][0] = true;
for (int j = 1; j <= psz; ++j)
if (p[j-1] == '*' && dp[0][j-1])
dp[0][j] = true;
for (int i = 1; i <= ssz; ++i)
for (int j = 1; j <= psz; ++j) {
if (p[j-1] != '*' && p[j-1] != '?')
dp[i][j] = (s[i-1] == p[j-1] && dp[i-1][j-1]);
else if (p[j-1] == '?')
dp[i][j] = dp[i-1][j-1];
else {
for (int k = i; k >= 0; --k)
if (dp[k][j-1]) {
dp[i][j] = true;
break;
}
}
}
return dp.back().back();
}
};
其中那个内部的循环的意思是:按照’*'为空,有一个,有两个。。。这样全部检查一遍,这样最终做出来的时间很长。
然后是一个关键的思路:
如果 ‘ * ’ 为空,则为dp[i][j-1],容易理解
如果‘ * ’不为空,至少有一个的话,就看dp[i-1][j],这个不太容易理解,原因是:
看dp[i-1][j],对于在j位置上的’*’,它可以为空,为一个,为两个。。。,那么对应到dp[i][j],那就是为一个,为两个。。。
class Solution {
public:
bool isMatch(string s, string p) {
int ssz = s.size(), psz = p.size();
vector<vector<bool>> dp(ssz+1, vector<bool>(psz+1, false));
dp[0][0] = true;
for (int j = 1; j <= psz; ++j)
if (p[j-1] == '*' && dp[0][j-1])
dp[0][j] = true;
for (int i = 1; i <= ssz; ++i)
for (int j = 1; j <= psz; ++j) {
if (p[j-1] != '*' && p[j-1] != '?')
dp[i][j] = (s[i-1] == p[j-1] && dp[i-1][j-1]);
else if (p[j-1] == '?')
dp[i][j] = dp[i-1][j-1];
else {
dp[i][j] = dp[i][j-1] || dp[i-1][j];
}
}
return dp.back().back();
}
};
和第10题有一些相似的地方的。
然后这一题还是有最优解法,不用dp,但是暂时没有看明白,以后有机会再看吧:
bool isMatch(string s, string p) {
int i = 0, j = 0;
int m = s.length(), n = p.length();
int last_match = -1, starj = -1;
while (i < m){
if (j < n && (s[i] == p[j] || p[j] == '?')){
i++; j++;
}
else if (j < n && p[j] == '*'){
starj = j;
j++;
last_match = i;
}
else if (starj != -1){
j = starj + 1;
last_match++;
i = last_match;
}
else return false;
}
while (p[j] == '*' && j <n) j++;
return j == n;
}
主要还是把那个dp的解法看明白