zoukankan      html  css  js  c++  java
  • leetcode 10. 正则表达式匹配

    题目

    给定一个字符串 (s) 和一个字符模式 (p)。实现支持 '.' 和 '*' 的正则表达式匹配。

    '.' 匹配任意单个字符。
    '*' 匹配零个或多个前面的元素。
    

    匹配应该覆盖整个字符串 (s) ,而不是部分字符串。

    说明:

    • s 可能为空,且只包含从 a-z 的小写字母。
    • p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *

    示例 1:

    输入:
    s = "aa"
    p = "a"
    输出: false
    解释: "a" 无法匹配 "aa" 整个字符串。
    

    示例 2:

    输入:
    s = "aa"
    p = "a*"
    输出: true
    解释: '*' 代表可匹配零个或多个前面的元素, 即可以匹配 'a' 。因此, 重复 'a' 一次, 字符串可变为 "aa"。
    

    示例 3:

    输入:
    s = "ab"
    p = ".*"
    输出: true
    解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。
    

    示例 4:

    输入:
    s = "aab"
    p = "c*a*b"
    输出: true
    解释: 'c' 可以不被重复, 'a' 可以被重复一次。因此可以匹配字符串 "aab"。
    

    示例 5:

    输入:
    s = "mississippi"
    p = "mis*is*p*."
    输出: false

    思路:

      这是一个经典的动态规划问题,在面试中经常考到,值得反复练习~

      首先确定状态,我们定义dp[i][j]:代表字符串s[0~(i-1)]和字符串p[0~(j-1)]的匹配状态,如果dp[i][j]==1,则说明s[0~(i-1)]能被p[0~(j-1)]匹配,反之,当dp[i][j]==0,则说明 s[0~(i-1)]不能被p[0~(j-1)]匹配。

      接下来是初始化问题,dp[0][0]代表字符串s和字符串p都是空串,空串和空串肯定是能匹配的,所以dp[0][0] = 1;当只有字符串p是空串时,这时的字符串s和字符串p肯定是无法匹配的,所以dp[0.....n][0]=0;当只有字符串s是空串时,我们看下图的初始情况,“ab",”a*c*ab",其中“a*”,将会变成一个空串,所以在dp[0][2] = 1 ,它是由dp[0][0]决定的,这是一个状态转移,即当p[j-1] == '*'时,dp[0][j]=dp[0][j-2]。

      最后考虑状态转移,

      1. 当指针指向的两个字符相等时,即s[i-1]==p[j-1]或者p[j-1]=='.'(因为'.'可以匹配任意单字符),只有当dp[i-1][j-1]是匹配的,dp[i][j]才是匹配的,如下图中蓝色的位置,状态转移方程为 dp[i][j] = dp[i-1][j-1]

          2.当指针指向字符串p的‘*’时,即p[j-1]=='*'时,分两种情况

          ①s[i-1]!=p[j-2]&&p[j-2]!='.',也就是“kac","kb*ac",说明此时”b*“应该是一个空串,当是空串的转移方程前面提到过,dp[i][j]=dp[i][j-2]

          ②s[i-1]==p[j-2]||p[j-2]=='.',此时的”*“可以匹配0个,一个,多个前面的元素

             a.当"*"匹配前面0个元素,也就是空串喽~dp[i][j]=dp[i][j-2]

             b.当”*“匹配前面一个元素时,也就是“a","a*"这种情况,只要字符串s”*“前面的匹配了就可以,状态转移为dp[i][j]=dp[i][j-1]

             c..当”*“匹配前面多个元素时,也就是“aaaa","a*"这种情况,状态转移为dp[i][j]=dp[i-1][j]

    代码:

    class Solution {
    public:
        bool isMatch(string s, string p) {
            int n = s.length();
            int m = p.length();
            int dp[n+1][m+1];
            memset(dp,0,sizeof(dp));
            dp[0][0] = 1;
            for(int i=2;i<=m;i++)
            {
                if(p[i-1]=='*' && dp[0][i-2]==1)
                {
                    dp[0][i] = 1;
                }
            }
            for(int j=1;j<=m;j++)
            {
                for(int i=1;i<=n;i++)
                {
                    if(s[i-1]==p[j-1] || p[j-1]=='.')
                    {
                        dp[i][j] = dp[i-1][j-1];
                    }
                    else if(p[j-1]=='*')
                    {
                        if(s[i-1]!=p[j-2])
                            dp[i][j] = dp[i][j-2];
                        if(s[i-1]==p[j-2]||p[j-2]=='.')
                            dp[i][j] = dp[i][j-1] + dp[i-1][j] + dp[i][j-2];
                    }
                }
            }
            return dp[n][m] != 0 ;
        }
    };
  • 相关阅读:
    MSDN Magazine搞错了
    Visual Studio 2005中设置调试符号(Debug Symbols)
    BCB 6的问题
    吴裕雄天生自然Spring Boot使用Spring Data JPA实现人与身份证的一对一关系映射
    吴裕雄天生自然Spring BootSpring Data JPA
    吴裕雄天生自然Spring BootSpring Boot对JSP的支持
    吴裕雄天生自然Spring BootSpring Boot的异常统一处理
    吴裕雄天生自然Spring Boot使用Spring Data JPA实现Author与Article的一对多关系映射
    吴裕雄天生自然Spring Boot解决 Error creating bean with name 'entityManagerFactory' defined in class path resource
    吴裕雄天生自然Spring Boot@ExceptionHandler注解和@ControllerAdvice注解
  • 原文地址:https://www.cnblogs.com/simplekinght/p/10453354.html
Copyright © 2011-2022 走看看