LeetCode 算法题库【10】——正则表达式匹配

正则表达式匹配

题目描述:

ti
mu

解题思路:
  • 第一种:动态规划。这个方法的思路就是通过判断dp[i][j] ,也就是s的前i项和p的前j项是否匹配。后面的dp[a][b]中的ab就是在字符串和字符规律中的位置。先定义一个dp,全部放入False。先使得dp[0][0] = True这样可以避免都为空的情况,这种情况是可以匹配的。
  • 然后我们要明白几点,首先就是*是和它之前的那个字符有关,也就是a*可以是任何数值的a,当然也可以是0a。所以如果它为0,那么这个字符规律就少两个字符,如果此时仍能匹配,则也就是如果dp[0][i-1] == True,则可以推出dp[0][i+1] == True,这是一种情况。其次,.这个字符是可以代替任何字符的,但是只能代替一个字符,所以如果在匹配的时候出现了有.的情况,那么相对应另一个字符串的那个位置则可以忽略,因为这两个已经匹配了。最后这里,如果出现*,并且前一个字符对应字符串的字符不同,则说明这个*给前一个字符的数量为0,也就是减少了两个字符,所以dp[a+1][b+1] = dp[a+1][b-1]。如果说相同,那么这个*给的数量就是对应字符的数量,可以全部抵消。最后考虑一些特殊情况,完善就可以了。
  • 时间复杂度:O(MN)
class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        s_len = len(s)
        p_len = len(p)
        dp = [[False] * (p_len + 1) for _ in range(s_len + 1)]
        dp[0][0] = True # 给定一个哨兵节点。
        for i in range(p_len):
            if p[i] == "*" and dp[0][i-1]:
                dp[0][i+1] = True
        for a in range(s_len):
            for b in range(p_len):
                if p[b] == s[a] or p[b] == ".":
                    dp[a+1][b+1] = dp[a][b]
                elif p[b] == "*":
                    if p[b-1] != s[a]:
                        dp[a+1][b+1] = dp[a+1][b-1]
                    if p[b-1] == s[a] or p[b-1] == ".":
                        dp[a+1][b+1] = (dp[a+1][b] or dp[a][b+1] or dp[a+1][b-1])
        return dp[-1][-1]

1

  • 第二种:递归的方法。首先还是检验两个是否为空的情况, 这里如果p为空的时候,判断s是否为空,从而知道返回True还是False。然后,判断匹配规则是否只有一个,如果为1,则判断匹配字符串长度是否为1,并且两者的第一个元素是否相同,或者说匹配规律为字符.,这里排除了规律为1的情况。之后开始重头戏递归,既然有两个及以上的匹配规律字符,那么已知这个*是代表前一个字符的,所以第一个字符不会是*,因此判断第二个字符是否为*。如果说第二个字符不是*,则如果要能够匹配,那么字符串和规则的第一个字符一定要能够匹配,也就是相同或者规则为.,如果匹配了,那么就进行递归,将前面已经匹配的第一个字符去掉,也就是用切片,将s[1:]p[1:]重新回到函数中,同样的方法检验下一个字符。直到当前切片中的第二个元素不为*,也就是p[1] == "*",则进行下一步while循环,这里同样是要保证s非空,其次字符串和规则的首元素都要能够匹配,然后进行递归判断,判断s是否能匹配第三个元素及之后的规则,也就是p[2:],如果都能匹配,那么可以直接说明整体匹配成功,返回True。如果还不行,则把当前字符串的第一个字符用切片去掉,再继续判断,直到第一个字符和第一个规则不匹配了,退出循环,然后再去判断这之后的是否匹配。匹配就会直接返回True,不匹配就会返回False,然后递归结束。
  • 这个方法比较基础,虽然说运行速度满了许多,但是这个思想需要掌握。
class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        if not p:
            return not s
        if len(p) == 1:
            return len(s) == 1 and (s[0] == p[0] or p[0] == ".")
        if p[1] != "*":
            if not s:
                return False
            return (s[0] == p[0] or p[0] == ".") and self.isMatch(s[1:], p[1:])
        while s and (s[0] == p[0] or p[0] == "."):
            if self.isMatch(s, p[2:]):
                return True
            s = s[1:]
        return self.isMatch(s, p[2:])

2

  • 第三种:用到python的模块re来解决问题,这是python的一种解决正则表达式的模块。当我看到这个方法的时候,我觉得很神奇,但是相对技术含量就没有那么高了,所以这个方法比较适合学完前两种方法之后再看看了解。当然我对这个方法的也没有怎么看懂,主要是需要我们了解这个模块中的这个方法的作用。
  • 参考学习资料:python正则表达式
import re
class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        p = re.search(p, s)
        if p and p.group() == s:
            return True
        else:
            return False
# or
		# return True if re.compile(p).fullmatch(s) else False

3

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值