LeetCode-Wildcard Matching-通配符匹配-DP
https://oj.leetcode.com/problems/wildcard-matching/
最终AC的方案是DP,并使用了一些技巧减少DP内存。
首先容易推出递推关系:
f (i,j) :后面已经匹配的情况下,前i个s字符和前j个p串字符是否能匹配?
则视p[j-1]为'?' , '*'或者一般字符进行递推。
还需要处理一下边界条件:
1)f(0,0)=1。此时所有的串都被一一匹配。
2)f(0,j:j>0),注意如果p[]中全是*,那么f(0,j)也是可能为1的,空串被匹配。
3)f(i:i>0,0)=0,用来匹配的p用完了,此时必然为0
这样进行DP,再利用奇偶数组交替就可以满足内存消耗。
但是这样仍然不能AC,题目设计者居然用了一个case里面p[]超大,这时还是会超时。
我用了个hack的方法:数p[]中有效字符(不为*)的,如果大于s[]中的,则肯定不能匹配,这样勉强AC。还有什么更好的方案么?
const int MAX_L=100000;
class Solution {
public:
int m,n;
int dp[2][MAX_L+1];
bool isMatch(const char *s, const char *p) {
memset(dp,-1,sizeof(dp));
n=strlen(s);
m=strlen(p);
int count=0;
for (const char *i=p;*i !='\0';i++){
if (*i!='*'){
count++;
}
}
if (count>n){return false;}
dp[0][0]=1;
bool empty=true;
for (int i=1;i<=m;i++){
if (p[i-1]!='*'){
empty=false;
}
dp[0][i]=empty;
}
for (int i=1;i<=n;i++) {
int cur=i%2;
int prev=(i-1)%2;
dp[cur][0]=0;
for (int j=1;j<=m;j++){
switch(p[j-1]){
case '?':
dp[cur][j]=dp[prev][j-1];
break;
case '*':
dp[cur][j]=dp[prev][j] | dp[cur][j-1] | dp[prev][j-1];
break;
default:
if (s[i-1]==p[j-1]){dp[cur][j]=dp[prev][j-1];}
else {dp[cur][j]=0;}
break;
}
}
}
return dp[n%2][m];
}
};
浙公网安备 33010602011771号