[回溯][dp]leetcode44:通配符匹配(hard)

题目:

44.通配符匹配

题解:

  • 解法1:回溯法
  • last:用来记录最后一次匹配的位置;star:用来记录*的位置
  • 开始进行匹配,若i小于s串的长度,进行for循环。若当前两个字符相等,或着p中的字符是问号(),则i和j分别加1。若 p[j] 是星号,要记录星号的位置,star赋为j,此时j再自增1,last赋为i。若当前 p[j] 不是星号,并且不能跟 p[i] 匹配上,此时就要靠*了,也就是我们要进行回溯了,i回到最后一个匹配位置+1,即让*吞掉一个字符,j继续回到*的下一个字符了,直至遍历完s。注意:我们还需要注意p在完成完成匹配后多余的*号需要处理,最后在判断j是否为p的长度来确定匹配成功与否了。

  • 解法2:动态规划
  • dp[i][j]:表示s的前i个字符与p的前j个字符是否匹配
  • 状态转移方程:
  • 1)若s[i] == p[j] || p[j] == '?',则s的前i个字符与p的前j个字符匹配与否取决于s的前i-1个字符与p的前j-1个字符匹配与否了,则dp[i][j] = dp[i-1][j-1]
  • 2)若p[j] == '*',则有两种情况,一是*与空串匹配,比如abab*,那么此时的dp[i][j] = dp[i][j-1](b与*匹配,改为b与b匹配);二是*与非空字符匹配,比如abcdab*,那么此时的dp[i][j] = dp[i-1][j](c与*匹配,改为b与*匹配,在改为b与b匹配)
  • 3)初始化:dp[0][j],s为空与p匹配,所以只要p开始为*才为true

代码如下:

class Solution {
public:
    //解法1:回溯法
    bool isMatch_1(string s, string p) {
        int j=0;
        
        //last用来记录最后一次匹配的位置+1,star用来记录*的位置
		for(int i=0, last=0, star=-1; i<s.length();){
            //一对一匹配,匹配成功一起移
			if(j<p.length() && (s[i]==p[j] || p[j]=='?')){
				++i;
				++j;
			}
			else if(j<p.length() && p[j]=='*'){
				last=i;         //last来记录最后一次匹配的位置
				star=j++;       //star用来记录*的位置
			}
			else if(star!=-1){  //匹配失败
				i=++last;       //i回到最后一个匹配位置+1,即让*吞掉一个字符
				j=star+1;       //j跳到*的下一个字符了
			}
			else return false;
		}
        /*用来p中处理多余的*的*/
		for(; j<p.length() && p[j]=='*'; ++j);
        /*匹配的结束条件:j到达p的尾端*/
		return j==p.length();
    }
    
 	//解法2:动态规划
    //dp[i][j]:表示s的前i个字符与p的前j个字符是否匹配
     bool isMatch(string s, string p) {
        int m = s.length();
        int n = p.length();
        vector<vector<bool>> dp(m + 1, vector<bool>(n + 1, false));
        
        //两个空字符串,肯定匹配
        dp[0][0] = true;
        
        //s为空与p匹配,所以只要p开始为*才为true
        for (int j = 1; j <= n; j++) {
            if(p[j - 1] == '*') dp[0][j] = true;
            else break;
        }
        
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                //若*与空串匹配,则dp[i][j]=dp[i][j-1],比如ab与ab*
                //若*与非空字符匹配,则dp[i][j]=dp[i-1][j],比如abcd与ab*
                if (p[j-1] == '*')
                {
                    dp[i][j] = dp[i][j-1] || dp[i-1][j];
                }
                
                //匹配成功
                else if (p[j-1] == '?' || s[i-1] == p[j-1]) 
                {
                    dp[i][j] = dp[i-1][j-1];
                } 
                
                //其他情况,dp[i][j]为false
                else 
                {
                    dp[i][j] = false;
                }
            }
        }
        return dp[m][n];
    }
};

你可能感兴趣的:(leetcode刷题,#,回溯,#,动态规划)