(leetcode刷题)
正则表达式匹配
题目: 给你一个字符串s
和一个字符规律p
,请你来实现一个支持 .
和 *
的正则表达式匹配。匹配,要涵盖整个字符串s
的,而不是部分字符串。
"." 匹配任意单个字符
"*" 匹配零个或多个前面的那一个元素(将*前面的元素重复0~n次)
s 可能为空,且只包含从 a-z 的小写字母
p 可能为空,且只包含从 a-z 的小写字母,以及字符 "." 和 "*"。
示例: 输入:s = "aa",p = "a"
;输出: false
输入:s = "ab",p = ".*"
;输出: true
方法
- 以下来自leetcode官方解答:链接
- 第一种:回溯。
class Solution:
def isMatch(self, s: str, p: str) -> bool:
# 若匹配文本为空,返回原文本是否为空值的bool值
if not p :return not s
# 当前字符匹配需要同时的两个条件:原文本不是空集;匹配的字符是"."或与原文本字符相同
first_match = bool(s) and p[0] in {s[0], '.'}
# 匹配字符大于2且第二个字符是"*",分为两种情况递归皆可
if len(p) >= 2 and p[1] == '*':
# 第一种:"*"匹配零个元素,即将前两个字符默认跳过
return (self.isMatch(s, p[2:]) or
# 第二种:当前字符相同的情况下进行下一个字符判定
first_match and self.isMatch(s[1:], p))
else:
# 若匹配字符的第二个字符不是"*",判断当前字符是否匹配,递归下一个
return first_match and self.isMatch(s[1:], p[1:])
- 第二种:动态规划
class Solution:
def isMatch(self, s: str, p: str) -> bool:
memo = {}
def dp(i, j):
if (i, j) not in memo:
# 若匹配字符串已经遍历,则判断原字符串是否以及完全遍历
if j == len(p):
ans = i == len(s)
else:
# 在未遍历完之前,判断当前字符是否匹配
first_match = i < len(s) and p[j] in {s[i], '.'}
# 若后一个字符是"*"
if j+1 < len(p) and p[j+1] == '*':
# 要么跳过匹配的当前两个字符(匹配零个)要么判断第一个字符和后一个(匹配多个)
ans = dp(i, j+2) or first_match and dp(i+1, j)
else:
# 否则判断当前字符,递归下一个
ans = first_match and dp(i+1, j+1)
# 递归结束后返回结果
memo[i, j] = ans
return memo[i, j]
return dp(0, 0)