• leetcode 剑指offer 19:正则表达式匹配


    题目描述:
    请实现一个函数用来匹配包含’. ‘和’*’ 的正则表达式。模式中的字符’.‘表示任意一个字符,而’*‘表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"aba"均不匹配。
    示例 1:
    输入:
    s = “aa”
    p = “a”
    输出: false
    解释: “a” 无法匹配 “aa” 整个字符串。
    示例 2:
    输入:
    s = “aa”
    p = "a
    "
    输出: true
    解释: 因为 ‘’ 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 ‘a’。因此,字符串 “aa” 可被视为 ‘a’ 重复了一次。
    示例 3:
    输入:
    s = “ab”
    p = ".
    "
    输出: true
    解释: "." 表示可匹配零个或多个('’)任意字符(’.')。
    示例 4:
    输入:
    s = “aab”
    p = “cab”
    输出: true
    解释: 因为 ‘’ 表示零个或多个,这里 ‘c’ 为 0 个, ‘a’ 被重复一次。因此可以匹配字符串 “aab”。
    示例 5:
    输入:
    s = “mississippi”
    p = "mis
    isp."
    输出: false
    s 可能为空,且只包含从 a-z 的小写字母。
    p 可能为空,且只包含从 a-z 的小写字母以及字符 . 和 ,无连续的 '’。
    思路: 动态规划
    字符串的动态规划,尤其是涉及到两个字符串匹配的问题,状态的定义都是:
    dp[i][j] 第一个字符串的前i 个字符 与第二个字符串的前j个字符
    这样定义之后一定要注意后面状态转移的时候字符串下标具体值(前j个是到下标j-1)
    具体地状态转移,需要根据题目中的要求进行,在本题的要求下,具体的状态转移过程详见代码:

    class Solution:
        def isMatch(self, s: str, p: str) -> bool:
            m, n = len(s), len(p)
            dp = [[False for _ in range(n+1)] for _ in range(m+1)]
            dp[0][0] = True
            # 为0的时候的判断: 相当于初始
            for a in range(1, n+1):
                if a == 1 and p[0] == '*':
                    dp[0][1] = True
                if p[a-1] == '*' and a >= 2:   # 这块一定不要忘
                    dp[0][a] = dp[0][a-2]
            for i in range(1, m+1):
                for j in range(1, n+1):
                    if s[i-1] == p[j-1] or p[j-1] == '.':   # 相等和为.的转移
                        dp[i][j] = dp[i-1][j-1]
                    elif p[j-1] == '*' and j >= 2:  # 为*时进行分情况讨论
                        if p[j-2] == '*':  # 两个连续的*相当于一个
                            dp[i][j] = dp[i][j - 1]
                        elif p[j-2] == '.':  # 有一个.相当于可以抵前面好几个,所以具体进行或运算,即第二个字符串j-2前的部分可以匹配上,后面剩下的部分都可以用.进行匹配
                            t = 0
                            while t <= i:
                                dp[i][j] |= dp[t][j-2]
                                t += 1
                        elif p[j-2] == s[i-1]:  # 看看把前一个字符重复一定的次数,是否可以匹配上,具体地还是进行或运算
                            count, k = 0, i-1
                            while k >= 0 and s[k] == p[j-2]:
                                dp[i][j] |= dp[i-count][j-1]
                                count += 1
                                k -= 1
                            dp[i][j] |= dp[i][j - 2]  # 把前一个字符去掉,即不进行重复,即便是相同的
                        elif p[j-2] != s[i-1]:  # 如果j-2字符和i-1不一样,即*前的字符和i-1不一样,就把这个去掉看是否可以匹配
                            dp[i][j] = dp[i][j-2]
            # print(dp)
            return dp[m][n]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
  • 相关阅读:
    前端智能化实践——可微编程
    C++异常处理
    RAG、数据隐私、攻击方法和安全提示
    10_创建和管理表
    [附源码]计算机毕业设计汽配管理系统Springboot程序
    Elasticsearch跨集群检索配置
    RT-Smart 应用开发笔记:fopen 造成文件被清空问题的分析记录
    Unity json反序列化为 字典存储
    Spring注入和生命周期
    【Android笔记49】Android中几种常见的数据适配器的使用(ArrayAdapter、BaseAdapter、SimpleAdapter)
  • 原文地址:https://blog.csdn.net/coding_diamond/article/details/125423678