• [LeetCode] Wildcard Matching


    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]==''){
                return s[i]=='';
            }
            if(p[j]!='*'){
                return ((s[i]==p[j] || p[j]=='?'&&s[i]!='') && matchHelper(s, p, i+1, j+1));
            }
            
            //p[j]=='*'
            while(s[i]!=''){
                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] == ''){
    			return s[i] == '';
    		}
    		if (p[j] != '*'){
    			return ((s[i] == p[j] || p[j] == '?'&&s[i] != '') && matchHelper(s, p, i + 1, j + 1));
    		}
    
    		//p[j]=='*'
    		while (s[i] != ''){
    			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] == ''){
    			return (d[i][j] = s[i] == '');
    		}
    		if (p[j] != '*'){
    			return (d[i][j] = (s[i] == p[j] || p[j] == '?'&&s[i] != '') && d[i + 1][j + 1] && matchHelper(s, p, i + 1, j + 1, d));
    		}
    
    		//p[j]=='*'
    		while (s[i] != ''){
    			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]!=''; str++, ptr++){
    		    switch(p[ptr]){
    		        case '?':
    		            break;
    		        case '*':
    		            star = true;
    		            sStart = str, pStart = ptr;
    		            while(p[pStart]=='*'){
    		                pStart++;
    		            }
    		            if(p[pStart]==''){
    		                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]=='';
    	}
    };



  • 相关阅读:
    C#后台利用正则表达式查找匹配字符
    C# Dictionary 的几种遍历方法
    eval解析JSON中的注意点
    jquery datatables api (转)
    Replication--镜像+复制
    Replication--分区+复制
    Replication--进程无法在“xxxx”上执行“sp_replcmds”
    Replication--无法将事务提升为分布式事务,因为在事务中有活动的保存点
    Replication--使用MSlogreader_history查看日志读起的延迟和事务命令
    Partition--分区拆分和分区合并
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7210544.html
Copyright © 2020-2023  润新知