10. 正则表达式匹配
10. 正则表达式匹配
题意
给定一个字符串 (s) 和一个字符模式 (p)。实现支持 '.' 和 '*' 的正则表达式匹配。
'.' 匹配任意单个字符。
'*' 匹配零个或多个前面的元素。
匹配应该覆盖整个字符串 (s) ,而不是部分字符串。
说明:
s可能为空,且只包含从a-z的小写字母。p可能为空,且只包含从a-z的小写字母,以及字符.和*。
示例 1:
输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。
解题思路
需要注意的是,和之前做的题不一样,这里*代表的是匹配前一个字符的0次或者n次,比如a*表示匹配0到n个字符a。
回溯
空:如果此时P为空,S也为空,则返回True,相反,如果其中一方为空,一方不为空,则返回False;
一个字符:如果此时双方都只有一个字符,那么直接比较即可;
多个字符:有两种情况:如果P的第二个字符不为
*,那么比较首字符,然后从双方的下一个位置开始继续的递归比较;如果为*的话,就让S不停的去匹配可能的P中的*,如果S还是无法匹配成功的话,就抛弃掉P中的*,然后让P从后面两个字符继续和当前的S进行比较;
dp
假定
dp[i][j]表示p的第j个字母可以匹配到s的第i个字母,有以下几种情况:如果
p[j] = s[i]:dp[i][j] = dp[i-1][j-1];如果
p[j] == .:dp[i][j] =dp[i-1][j-1];
实现
class Solution(object):
def isMatch(self, s, p):
"""
:type s: str
:type p: str
:rtype: bool
"""
if not p:
return len(s) == 0
if len(p) == 1:
return len(s) == 1 and (s[0] == p[0] or p[0] == '.')
# 不为*则直接比较第一个,然后双方继续递归
if p[1] != '*':
return len(s) != 0 and (p[0] == s[0] or p[0] == '.') and self.isMatch(s[1:], p[1:])
# 剩下的语句说明P存在*
# S中可能存在多个相同的匹配元素,比如aaaa和a*,S需要一直移动,同时还要在移动的过程中和P的两个字符后面去比较(因为第一个字符已经相等,而第二个字符则为*),只要匹配成功一个,就返回True,反之S会一直移动到为空
while s and (s[0] == p[0] or p[0] == '.'):
if self.isMatch(s, p[2:]):
return True
s = s[1:]
# 之前匹配P中的*不成功,且S和P也不能够再匹配了,所以查看下一个P中的*和现在的S来做匹配
return self.isMatch(s, p[2:])
def isMatch(self, s, p):
"""
:type s: str
:type p: str
:rtype: bool
"""
lenS, lenP = len(s), len(p)
dp = [[False] * (lenP + 1) for i in range(lenS + 1)]
# initialization, when p is empty, always Flase, when s is empty:
dp[0][0] = True
for j in range(2, lenP + 1): dp[0][j] = dp[0][j - 2] and p[j - 1] == '*'
# dp
for i in range(1, lenS + 1):
for j in range(1, lenP + 1):
dp[i][j] = dp[i][j - 2] or (p[j - 2] in (s[i - 1], '.') and dp[i - 1][j]) if p[j - 1] == '*' \
else dp[i - 1][j - 1] and p[j - 1] in ('.', s[i - 1])
return dp[lenS][lenP]
关注公众号:数据结构与算法那些事儿,每天一篇数据结构与算法

浙公网安备 33010602011771号