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

  

posted @ 2014-10-02 16:38  zombies  阅读(253)  评论(0编辑  收藏  举报