44. 通配符匹配

题目描述

Implement wildcard(通配符) pattern matching with support for?and*(Linux命令行*.txt,通配符)。? 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

方法1

常规思路,动态规划

class Solution {
public:
    bool isMatch(const char *s, const char *p) {

        int m = strlen(s);
        int n = strlen(p);
        //为了递推公式的方便,我们需要人为的创造长度为0时的情况,
        //所以这里的dp用的是长度而不是下标
        vector<vector<bool>> dp(m+1,vector<bool>(n+1,false));        
        dp[0][0] = true;        
        for(int i=1; i<=n; i++)
        {
            //*除了可以匹配任意长度的字符串外,还可以匹配空串
        	if(p[i-1] == '*')//匹配空串
        		dp[0][i] = dp[0][i-1];           
        } //根据我们的初始化dp时的情况,天然的dp[i][0]=false,1<=i<=m       
        for(int i=1; i<=m; i++)
        {
            for(int j=1; j<=n; j++)
            {
                if(p[j-1]==s[i-1] || p[j-1]=='?')
                    dp[i][j] = dp[i-1][j-1];               
                else if(p[j-1] == '*')//'*'如何匹配使用,不同的状态转移机
                	     //'*'匹配一个空串    '*'这里匹配一个非空串,串的末尾为s[i-1]  
                    dp[i][j] = dp[i][j-1] || dp[i-1][j];//即'*'匹配为'*s[i-1]'
            }
        }        
        return dp[m][n]; 
    }
};

方法2

主要是''的匹配处理。遇到''就跳过去,优先用''后面的来匹配。如果''后面的匹配不上,则用''匹配一个字符,再看''后面的能否匹配上。。。。。不匹配时往最近的*回溯,这个思路不是能完全理解。

class Solution {
public:
    bool isMatch(string s, string p) {
        
        int m = s.length();
        int n = p.length();
        if(m==0 && n==0)
        	return true;
        if(m!=0 && n==0)
        	return false;
    	int i = 0;
	    int j = 0;
	    int last = -1;//p中最近出现的'*'的下标
	    int lastStart = 0;//最近的一次对'*'的匹配做出的处理后i开始要匹配的下标
	    while(i < m) 
	    {
	    	if(j<n && (p[j] == '?' || p[j]==s[i])) 
	    	{
	    		++i;
			    ++j;
		    }             //*按照匹配0个,1个,2个,。。。的顺序使用
		    else if(j<n && p[j]=='*')//由于这是遇到的新的*,初次匹配空串,优先使用后面的 
		    {
		    	last = j;		
			    lastStart = i;
			    j++;
		    } 
		    else if(last != -1)//可以对应着思考使用动态规划时 
		    {                 //的递推公式中的状态转移方程式
		    	j = last + 1;
			    i = lastStart+1;
			    lastStart = i;
		    } 
		    else
		    	return false;
		}
	    while(j<n && p[j]=='*') ++j;
	    return j == n;
    }
};

除了以上方法之外,我们还可以使用传统的递归函数思路。

posted on 2021-04-05 10:58  朴素贝叶斯  阅读(72)  评论(0编辑  收藏  举报

导航