LeetCode刷题(python版)——Topic10正则表达式匹配

一、题设

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

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

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

 

示例 1:

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

示例 2:

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

示例 3:

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

二、基本思路

         这题属于动态规划题。

        首先,由题意知,‘*’可以匹配多个字符,‘.’可匹配单个字符。那么若s="abc"时,p="ab*”或p="ab."都可以适配s;若s="abc"时,p="a*"也可以适配它,但是p="a."就无法适配s。我们记动态数组flag[a][b] = false表示s[0:a-1]与p[0:b-1]不适配。

        所以p与s的匹配分为以下几种情况:

        1. 当p[j-1] != '*'时,那么就比较p[j-1]与s[i-1]是否相等,或p[j-1]="."也可以(p[j-1]可以当成任意字符与s[i-1]匹配),若相等,则flag[i][j] = flag[i-1][j-1](比较前s[0,i-2]与p[0,j-2]即可)

        2.当p[j-1] == '*'时,那么可以将p[j-2]与'*'看成一个整体,即表示p[j-2]在s中匹配了0次或多次。值得注意的是匹配了0次和多次只要有一次成功即为匹配成功。

                2.1 若p[j-2]与'*'匹配了0次,那么即p[j-2]与‘*’自己消除了,所以flag[i][j] = flag[i][j-2](比较前s[0,i-1]与p[0,j-3]即可)。

                2.2 若p[j-2]与'*'匹配了多次(0次以上),判断p中"*"前的字符与s最后一个字符是否相同或者p中"*"前的字符为'.'也一样成立,所以flag[i][j] = flag[i-1][j](比较前s[0,i-2]与p[0,j-1]即可)

三、代码实现

  def isMatch(self, s: str, p: str) -> bool:
        m = len(s)
        n = len(p)
        # 动态分配数组,注意长度得加一。
        flag = [[False for i in range(n+1)] for j in range(m+1)]
        for i in range(m+1):
            for j in range(n+1):
                # 当模式串为空
                if j == 0:
                    # 当字符串为空
                    if i == 0:
                        flag[i][j] = True
                # 模式串不为空
                else:
                    # 最后一位不为*
                    if p[j-1] != "*":
                        # 正常字母比较或者"."匹配任意字符
                        if (j >=1 and p[j-1]==s[i-1] or p[j-1] == "."):             # 这样是否成立就与前段字符串有关
                            flag[i][j] = flag[i-1][j-1]
                    # 最后一位为*
                    else:
                        # 可能匹配0次,舍弃p[j-1]与p[j-2]
                        if j >=2:
                            flag[i][j] |= flag[i][j-2]
                        # 也可能匹配多次,判断p中"*"前的字符与s最后一个字符是否相同或者p中"*"前的字符为'.'也一样成立,两种情况成功一种即匹配成功
                        if (j>=2 and i>=1 and (p[j-2] == s[i-1] or p[j-2] =='.')):
                            flag[i][j] |= flag[i-1][j]
        return flag[m][n]

四、效率总结

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值