正则表达式匹配
题目描述:
解题思路:
- 第一种:动态规划。这个方法的思路就是通过判断
dp[i][j]
,也就是s
的前i
项和p
的前j
项是否匹配。后面的dp[a][b]
中的a
和b
就是在字符串和字符规律中的位置。先定义一个dp
,全部放入False
。先使得dp[0][0] = True
这样可以避免都为空的情况,这种情况是可以匹配的。 - 然后我们要明白几点,首先就是
*
是和它之前的那个字符有关,也就是a*
可以是任何数值的a
,当然也可以是0
个a
。所以如果它为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]
- 第二种:递归的方法。首先还是检验两个是否为空的情况, 这里如果
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:])
- 第三种:用到
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