44. 通配符匹配 leetcode 每日一题

题目连接

这个题目对dp思想的理解和对dp问题边界问题的处理很有帮助。

题解:定义dp[i][j]表示s的前i个字符和p的前j个字符是否可以匹配。

假如说p的第j个字符和s的第i个字符一样,那么dp[i][j]=dp[i-1][j-1],不一样的话,直接就是false

如果p的第j个字符是?,那么一定可以匹配成功。dp[i][j]=dp[i-1][j-1]。

如果p的第j个字符是*,这里*可以用,也不使用,如果不适用*的话,dp[i][j]=dp[i][j-1],直接由j-1个转移过来,如果使用的话,因为我们会想到*可能跟i-k~i这个字符串进行匹配。那么转移方程就不好确定了,其实没必要这样。如果*和i之前的k个字符匹配,我们直接就把问题丢个i-1就好了,因为i-1一定在i-k~i之间。也就是说第j个和第i-1个匹配,所以转移方程为dp[i][j]=dp[i-1][j],*具体匹配多长的字符串,我们没必要知道,只需要把问题丢给i-1和j就好了,这也是dp问题的精要之处。

class Solution {
public:
    bool isMatch(string s, string p) {
        int n=s.size();
        int m=p.size();
        vector<vector<int>> dp(n + 1, vector<int>(m + 1));
        dp[0][0]=1;
        for(int i=0;i<p.size();i++){
            if(p[i]=='*'){
                dp[0][i+1]=1;
            }
            else break;
        }
        for(int j=0;j<p.size();j++){
            for(int i=0;i<s.size();i++){
                if(p[j]=='?'||p[j]==s[i]) dp[i+1][j+1]=dp[i][j];
                else if(p[j]=='*') dp[i+1][j+1]=dp[i][j+1]|dp[i+1][j];
                else if(p[j]>='a'&&p[j]<='z') dp[i+1][j+1]=false;
            }
        }
        return dp[s.size()][p.size()];
    }
};

另外vector开二维数组也挺好用的。vector<vector<int> > dp(n + 1, vector<int>(m + 1,x));这是一个(n+1)*(m+1)的初始值为x的二维数组。

还有关于边界处理,dp问题的边界值是后续的基础,一般都是dp[i][0]和dp[0][i]。这个问题的边界值dp[0][0]=1,dp[i][0]一定是false,dp[0][i],如果字符串p前i个是*,那么就是1,否则还是false.

原文地址:https://www.cnblogs.com/Accepting/p/13292360.html