力扣10题(正则表达式)

10、正则表达式

基本思想:

动态规划

具体实现:

1.确认状态:

最后一步----dp[i][j],代表s[0:i]和p[0:j]是否匹配 

dp里面的i和j是s和p的长度

子问题---dp[i-1][j-1],dp[i][j-2],dp[i-1][j-2],dp[i-1][j]

2、状态转移公式:

 

 3、初始状态:

  • p为空串,s不为空串,肯定不匹配。
  • s为空串,但p不为空串,要想匹配,只可能是右端是星号,它干掉一个字符后,把 p 变为空串。
  • for j in range(1, p_len + 1):
                if p[j - 1] == '*':
                    dp[0][j] = dp[0][j - 2]
  • s、p都为空串,肯定匹配。 dp[0][0] = True

4、计算顺序:

从左到右  如果中间遇到False也不会退出,说不定往后走两步就碰到*,就变成Ture了,如果当下是False也会继续往后走

 

代码:

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        s_len = len(s)
        p_len = len(p)

        # dp[i][j] 表示 s[:i] 与 p[:j] 是否匹配,各自前 i、j 个是否匹配
        dp = [[False] * (p_len + 1) for _ in range(s_len + 1)]
        dp[0][0] = True

        # s 为空串
        for j in range(1, p_len + 1):
            # 若 p 的第 j 个字符 p[j - 1] 是 '*'
            # 说明第 j - 1、j 位可有可无
            # 那么如果前 j - 2 个已经匹配上,前 j 个也可以匹配上
            if p[j - 1] == '*':
                dp[0][j] = dp[0][j - 2]

        for i in range(1, s_len + 1):
            for j in range(1, p_len + 1):
                if p[j - 1] in {s[i - 1], '.'}: # A
                    dp[i][j] = dp[i - 1][j - 1]
                elif p[j - 1] == '*': # B
                    if p[j - 2] in {s[i - 1], '.'}: # (1)
                        dp[i][j] = dp[i][j - 2] or dp[i - 1][j - 2] or dp[i - 1][j]
                    else: # (2)
                        dp[i][j] = dp[i][j - 2]
        return dp[s_len][p_len]

 

posted @ 2021-03-16 16:08  最近饭吃的很多  阅读(151)  评论(0编辑  收藏  举报