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]; } };