0
点赞
收藏
分享

微信扫一扫

力扣Leetcode:10. 正则表达式匹配(Python)

题目描述

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。

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

所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

输入:s = “aa”, p = “a*”
输出:true
解释:因为 ‘*’ 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 ‘a’。因此,字符串 “aa” 可被视为 ‘a’ 重复了一次。

题解

由于我一开始想当然了,所以一开始写的这些是针对于“星号代表匹配零个或多个任意字符,也就是a*可以代表a,可以代表ab,可以代表abb”情况下的题解。

题目中的情况相对于上面的情况(也就是我想当然了的情况),有这样一些区别:

  • ‘*’ 匹配零个或多个前面的那一个元素。也就是说"a星"可以是零个a、一个a、两个a…

以下部分与之前的保持一致:

  • dp[i][j]代表s[0…i]能否匹配p[0…j]
  • 如果s[i]==p[j],那么这两个字符直接匹配,dp[i][j]=dp[i-1][j-1]。
  • 如果p[j]==‘.’,那么不管s[i]是什么字符都可以匹配,dp[i][j]=dp[i-1][j-1]。

剩下的难点在于p[j]=='*'的情况。

由于p[j]如果为星号,那么只能取p[j-1]的字符进行重复零次或若干次,因此分为两种情况:要么星号代表零次(相当于去掉p[j-1]),要么星号代表重复p[j-1]若干次(此时必然有p[j-1]==s[i])。这儿的两种情况为:

  • 若p[j-1] != s[i],那么这里的星号必然要代表重复零次,即去掉p[j-1],因此dp[i][j] = dp[i][j-2]。
  • 若p[j-1] == s[i] 或者 p[j-1] ==‘.’, 那么这个时候星号可以代表重复零次、一次或多次,对于下面的三种情况,只要有一种情况为True,结果就为True:
    • 情况1:
      abbbbbb
      ab*
      此时仍有很多很多的重复字符待匹配,先令dp[i][j]=dp[i-1][j],相当于先匹配一个字符,后面的字符后面再看。
    • 情况2:
      ab
      ab*
      此时星号只需要重复前面的字符一次就可以了,也就是说星号有没有都一样,因此dp[i][j]=dp[i][j-1]。
    • 情况3:
      a
      aa*
      此时虽然星号所能重复的字符与s匹配上了,但还是不能重复多次(只能消去星号前面的字符),dp[i][j]=dp[i][j-2]。

以及补充一些编程时的技巧:

  • 为了防止越界,我推荐dp数组多定义一个位置。即dp[i][j]代表s的前i个字符与p的前j个字符匹配。因此dp[0][0]=True。
  • python定义二维数组dp[m][n]:
    dp = [[False] * n for _ in range(m)]
  • 注意dp[i][j]对应s[i-1]与p[j-1]。
  • for循环中的i与j是否要从0开始?i要,j可以不要!因为空字符可以与非空模式(如a*)匹配,但非空字符肯定不会与空模式匹配。

虽然代码行数很短,但这道题目的确很复杂。

代码

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        m, n = len(s) + 1, len(p) + 1
        dp = [[False] * n for _ in range(m)]
        dp[0][0] = True
        for i in range(0, m):
            for j in range(1, n):
                if s[i - 1] == p[j - 1] or p[j - 1] == '.':
                    dp[i][j] = dp[i-1][j-1]
                if p[j - 1] == '*':
                    if j >= 2 and s[i - 1] != p[j - 2]:
                        dp[i][j] = dp[i][j-2]
                    if j >= 2 and (s[i - 1] == p[j - 2] or p[j - 2] == '.'):
                        dp[i][j] = dp[i-1][j] or dp[i][j-1] or dp[i][j-2]
        return dp[m - 1][n - 1]
举报

相关推荐

0 条评论