leetcode 10,44 (字符串匹配-动态规划解法汇总)

44. Wildcard Matching
题目链接:

44. Wildcard Matching

题意:

给定两个字符串s, p,其中p可能含有特殊字符?和*,判断能否用p来匹配s。 其中:
‘?’ Matches any single character.
‘*’ Matches any sequence of characters (including the empty sequence).

题目思路:

这是典型的一类字符串匹配与动态规划相结合的问题,记s字符串的长度为n,p字符串的长度为m。这里设dp[i][j]表示s的前i个字符与p的前j个字符匹配得到的结果。注意这里的i和j与字符串s,p的下标i,j相区分,比如dp[1][1]表示s[0]与p[0]相匹配得到的结果。我们要求的结果就是dp[n][m]。

我们现在把这个问题一步步简化:

  1. 首先我们考虑dp[0][0]=true,表示s和p都为空字符串时,两者自然是可以直接匹配上的
  2. 我们考虑如果仅仅p为""(空字符串),s不为空字符串,那么这时候dp[i][0]=false (i=1,2,…,n)
  3. 我们考虑仅仅s为""(空字符串),那么只有当p为"******"才有可能匹配的上,即:
    dp[0][j+1]=dp[0][j] (当前仅当p[j]==’*'可以转化)

接下来我们考虑一般性的情况:即dp[i+1][j+1]可能由哪些情况转化而来。

  1. 如果s[i]==p[j]或者说p[j]==’?’,那么这时候有:dp[i+1][j+1]=dp[i][j]
  2. 如果上式不成立,且p[j]==’*’,这时候也是有可能转化到dp[i+1][j+1]的
    这里我们考虑三种情况:
    5.1 p[j]直接与s[i]匹配,那么有:dp[i+1][j+1]=dp[i][j]成立 //例子:s: “ab”,p: “a*”
    5.2 p[j]匹配0个字符,那么有:dp[i+1][j+1]=dp[i+1][j]成立,//例子:s: “ab”, p: “ab*”
    5.3 p[j]匹配多个字符,那么有:dp[i+1][j+1]=dp[i][j+1]成立,//例子: s: “aa”, p:"*"

综合考虑上述情况可得代码:

class Solution {
public:
    //字符串匹配 通用的dp问题
    bool isMatch(string s, string p) {
        if(!s.size() && !p.size()) return true;
        if(s.size() && !p.size()) return false;
        int n=s.size();
        int m=p.size();
        vector<vector<bool>> dp(n+1,vector<bool>(m+1));//第(i,j)个字符 注意与s和p的下标i,j区分
        //边界条件 dp[0][0],dp[0][j],dp[i][0]
        dp[0][0]=true;
        //dp[i][0] 默认为false,p为""
        for(int j=0;j<m;j++){
            if(p[j]=='*') dp[0][j+1]=dp[0][j];
        }
        
        //处理dp[1..][j], dp[i][1..]的结果
        for(int i=0;i<n;i++){
            
            for(int j=0;j<m;j++){
                if(s[i]==p[j] || p[j]=='?') dp[i+1][j+1]=dp[i][j];//可以直接转化
                else if (p[j]=='*'){
                    bool tmp=dp[i+1][j];//*匹配的是""
                    bool tmp2=dp[i][j];//*匹配的是s[i]
                    bool tmp3=dp[i][j+1];//*匹配多个字符 ,这里注意匹配多个字符的情况 //例子s: "aa" ,p: "*"
                    dp[i+1][j+1]=(tmp || tmp2 || tmp3);
                }
            }
        }
        
        return dp[n][m];
    }
};
10. Regular Expression Matching
题目链接:

10. Regular Expression Matching

题意:

给定两个字符串s, p,其中p可能含有特殊字符?和*,判断能否用p来匹配s。 其中:
‘.’ Matches any single character.
‘*’ Matches zero or more of the preceding element.

题目思路:

与前面44题大同小异,不同点在于’*‘这个符号可以当前置符号消失。比如s: “ab”, p: "d*ab"这个也是匹配的上的,在44题的第5小布时讨论’*'的情况就可以,其余部分基本与44题相同

class Solution {
public:
    //dp
    bool isMatch(string s, string p) {
        if(!s.size() && (!p.size())) return true;
        int s1=s.size(),p1=p.size();
        
        vector<vector<bool>> dp(s1+1,vector<bool>(p1+1,false));
        
        //dp[0][0],dp[0][j],dp[i][0](这种情况全为false)
        dp[0][0]=true;//初始条件
        
        //排除p前面一直为*号的情况, p: ******XXXXX, s:XXXXX 也匹配
        //p: "" ,s: #*#*#*
        for(int j=1;j<p1;j+=2){
            dp[0][j+1]=((p[j]=='*') && dp[0][j-1]);//初始条件
        }
        
        for(int i=1;i<s1+1;i++){
            
            for(int j=1;j<p1+1;j++){
                
                if(s[i-1]==p[j-1] || p[j-1]=='.'){
                    dp[i][j]=dp[i-1][j-1];
                }
                
                else if(p[j-1]=='*' && j>=2){
                    bool tmp1=dp[i][j-2];//0个
                    if(p[j-2]=='.' || p[j-2]==s[i-1]) dp[i][j]=dp[i][j-1] || dp[i-1][j];//一个或者多个 多个时候的例子:s: "bbbc", p: "b*c"
                    dp[i][j]=dp[i][j]||tmp1;
                }
            }
        }
        
        return dp[s1][p1];
    }
};
posted @ 2020-09-28 22:38  xzhws  阅读(137)  评论(0编辑  收藏  举报