1. 程式人生 > >[LeetCode] Wildcard Matching

[LeetCode] Wildcard Matching

case consola har leetcode data reg 是否 details prototype

Wildcard Matching

Implement wildcard pattern matching with support for ‘?

and ‘*‘.

‘?‘ Matches any single character.
‘*‘ Matches any sequence of characters (including the empty sequence).

The matching should cover the entire input string (not partial).

The function prototype should be:
bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "*") → true
isMatch("aa", "a*") → true
isMatch("ab", "?*") → true
isMatch("aab", "c*a*b") → false

解題思路:

這道題與http://blog.csdn.net/kangrydotnet/article/details/46624353類似,註意這裏的*號與Regular Expression Matching不同。能夠採用Regular Expression Matching開發架構,用遞歸的方法。

可是會出現超時問題:

class Solution {
public:
    bool isMatch(string s, string p) {
        return matchHelper(s, p, 0, 0);
    }
    
    bool matchHelper(string& s, string& p, int i, int j){
        if(p[j]=='\0'){
            return s[i]=='\0';
        }
        if(p[j]!='*'){
            return ((s[i]==p[j] || p[j]=='?'&&s[i]!='\0') && matchHelper(s, p, i+1, j+1));
        }
        
        //p[j]=='*'
        while(s[i]!='\0'){
            if(matchHelper(s, p, i, j+1)) return true;
            i++;
        }
        return matchHelper(s, p, i, j+1);
    }
};
當輸入"aaabbbaabaaaaababaabaaabbabbbbbbbbaabababbabbbaaaaba", "a*******b"時,上述代碼超時。原因是有連續的*。於是修正輸入,將a******b改成a*b,例如以下:

class Solution {
public:
    bool isMatch(string s, string p) {
		string newP = "";
		for (int i = 0; i < p.length(); i++){
			if (i>0 && p[i - 1] == p[i] && p[i]=='*'){
				continue;
			}
			newP += p[i];
		}
		return matchHelper(s, newP, 0, 0);
	}

	bool matchHelper(string& s, string& p, int i, int j){
		if (p[j] == '\0'){
			return s[i] == '\0';
		}
		if (p[j] != '*'){
			return ((s[i] == p[j] || p[j] == '?'&&s[i] != '\0') && matchHelper(s, p, i + 1, j + 1));
		}

		//p[j]=='*'
		while (s[i] != '\0'){
			if (matchHelper(s, p, i, j + 1)) return true;
			i++;
		}
		return matchHelper(s, p, i, j + 1);
	}
};
當輸入很大的時候。仍然超時:

"abbabaaabbabbaababbabbbbbabbbabbbabaaaaababababbbabababaabbababaabbbbbbaaaabababbbaabbbbaabbbbababababbaabbaababaabbbababababbbbaaabbbbbabaaaabbababbbbaababaabbababbbbbababbbabaaaaaaaabbbbbaabaaababaaaabb", "**aa*****ba*a*bb**aa*ab****a*aaaaaa***a*aaaa**bbabb*b*b**aaaaaaaaa*a********ba*bbb***a*ba*bb*bb**a*b*bb"

經分析。遞歸調用時,會反復計算。能夠用一個二維數組d[i][j]記錄s[0...i]與p[0...j]是否匹配。

class Solution {
public:
	bool isMatch(string s, string p) {
		string newP = "";
		for (int i = 0; i < p.length(); i++){
			if (i>0 && p[i - 1] == p[i] && p[i] == '*'){
				continue;
			}
			newP += p[i];
		}

		int sLen = s.length();
		int pLen = newP.length();
		
		vector<vector<bool>> d(sLen + 1, vector<bool>(pLen + 1, true));

		return matchHelper(s, newP, 0, 0, d);
	}

	bool matchHelper(string& s, string& p, int i, int j, vector<vector<bool>>& d){
		if (p[j] == '\0'){
			return (d[i][j] = s[i] == '\0');
		}
		if (p[j] != '*'){
			return (d[i][j] = (s[i] == p[j] || p[j] == '?'&&s[i] != '\0') && d[i + 1][j + 1] && matchHelper(s, p, i + 1, j + 1, d));
		}

		//p[j]=='*'
		while (s[i] != '\0'){
			if ((d[i][j] = d[i][j + 1] && matchHelper(s, p, i, j + 1, d))) return true;
			i++;
		}
		return (d[i][j] = d[i][j + 1] && matchHelper(s, p, i, j + 1, d));
	}
};
這裏運用短路原則。

速度倒是很快。可是會產生內存溢出錯誤。由於空間復雜度為O(m*n)。


終於辦法參考水中的魚:http://fisherlei.blogspot.com/2013/01/leetcode-wildcard-matching.html,詳細仍不是非常明確:

class Solution {
public:
	bool isMatch(string s, string p) {
		bool star = false;
		int sStart = 0, pStart = 0;
		int str, ptr;
		for(str=sStart, ptr = pStart; s[str]!='\0'; str++, ptr++){
		    switch(p[ptr]){
		        case '?':
		            break;
		        case '*':
		            star = true;
		            sStart = str, pStart = ptr;
		            while(p[pStart]=='*'){
		                pStart++;
		            }
		            if(p[pStart]=='\0'){
		                return true;
		            }
		            str = sStart - 1;
		            ptr = pStart - 1;
		            break;
		        default:
		            if(s[str]!=p[ptr]){
		                if(!star){
		                    return false;
		                }
		                sStart++;
		                str = sStart-1;
		                ptr = pStart-1;
		            }
		            break;
		    }
		}
		while(p[ptr]=='*')
		    ptr++;
		return p[ptr]=='\0';
	}
};



[LeetCode] Wildcard Matching