[H]O-19 正则表达式匹配(Python)

本文解析了一个关于正则表达式匹配的问题,通过动态规划方法解决,详细讲解了如何使用状态转移方程处理'.', '*'字符。核心在于理解dp[i][j]与s[i-1], p[j-1]的关系,以及'*'字符的特殊情况处理。
摘要由CSDN通过智能技术生成

[H]O-19 正则表达式匹配

题目

请实现一个函数用来匹配包含’. ‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"ab*a"均不匹配。

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

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

输入:
s = "aab"
p = "c*a*b"
输出: true
解释: 因为 '*' 表示零个或多个,这里 'c'0, 'a' 被重复一次。因此可以匹配字符串 "aab"。
示例 5:

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

解决方法:动态规划

设 ss 的长度为 nn , pp 的长度为 mm ;将 ss 的第 ii 个字符记为 s_i,pp 的第 j个字符记为 p_j ,将 ss 的前 i个字符组成的子字符串记为 s[:i] , 同理将 pp 的前 j个字符组成的子字符串记为 p[:j]。

因此,本题可转化为求 s[:n] 是否能和 p[:m] 匹配
总体思路是从 s[:1] 和 p[:1] 是否能匹配开始判断,每轮添加一个字符并判断是否能匹配,直至添加完整个字符串 s 和 p。
本题的状态共有 n×m 种,应定义状态矩阵dp ,dp[i][j] 代表 s[:i] 与 p[:j] 是否可以匹配。
做好状态定义,接下来就是根据 「普通字符」 , 「.」 , 「*」三种字符的功能定义,分析出动态规划的转移方程。

1.初始化

当s,p均为空时,匹配——dp[0][0]=True
当s非空,p为空,不可能匹配。
当s是空串,p不是的时候,如下才可:(满足偶数位为*才有可能)
在这里插入图片描述
在这里插入图片描述

2.返回值

dp 矩阵右下角字符,代表字符串 s 和 p 能否匹配。

3.当s,p均非空时,遍历

状态定义: 设动态规划矩阵 dp , dp[i][j] 代表字符串 s 的前 i 个字符和 p 的前 j 个字符能否匹配。

转移方程: 需要注意,由于 dp[0][0] 代表的是空字符的状态, 因此 dp[i][j] 对应的添加字符是 s[i - 1] 和 p[j - 1] 。

当 p[j - 1] = ‘*’ 时, dp[i][j] 在当以下任一情况为 true 时等于 true :

  1. dp[i][j - 2]: 即将字符组合 p[j - 2] * 看作出现 0 次时,能否匹配;(如a和ab*)
  2. dp[i][j - 1]: 即将字符组合 p[j - 2] * 看作出现 1 次时,能否匹配;(如ab和ab*)
  3. dp[i - 1][j] 且 s[i - 1] = p[j - 2]: 即让字符 p[j - 2] 多出现 1 次时,能否匹配;(如abb和ab*)
  4. dp[i - 1][j] 且 p[j - 2] = ‘.’: 即让字符 ‘.’ 多出现 1 次时,能否匹配;(如abb和a.*)

当 p[j - 1] != ‘*’ 时, dp[i][j] 在当以下任一情况为true 时等于 true :

  1. dp[i - 1][j - 1] 且 s[i - 1] = p[j - 1]: 即让字符 p[j - 1] 多出现一次时,能否匹配;(abc和abc)
  2. dp[i - 1][j - 1] 且 p[j - 1] = ‘.’: 即将字符 . 看作字符 s[i - 1] 时,能否匹配;(abc和ab.)

python代码

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





在这里插入图片描述
-----2021/1.8遇到的第一道hard,这个动态规划好厉害。。。糊里糊涂.jpg-------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值