• 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.

  • 相关阅读:
    [WP8] ListBox的Item宽度自动填满
    [WP8] Binding时,依照DataType选择DataTemplate
    [CLK Framework] CLK.Threading.PortableTimer
    Sql Server 中 根据列名查询表名
    hMailServer SSL 配置
    SmtpClient SSL 发送邮件异常排查
    hMailServer 配置
    ADO.NET 连接池 Session 状态分析
    SqlBulkCopy 参数配置示例
    arrow css
  • 原文地址:https://www.cnblogs.com/Accepting/p/13292360.html
Copyright © 2020-2023  润新知