问题
解答
1.递归算法
先考虑*
。*
只会出现在第二个字符之后,且有两种可能。
- 匹配零个前面的那一个元素
返回第一个字符是否匹配和后面字符是否全部符合的bool
值 - 匹配一个或多个前面的那一个元素
忽略s'
的第一个元素,判断s'
的每一个字符除第一个元素和p'
是否匹配或者判断忽略p'
匹配的一部分后二者是否匹配
时间复杂度: O(2^n)
class Solution:
def isMatch(self, s: str, p: str) -> bool:
if not p:
return not s
first = bool(s and p[0] in {s[0],'.'})
if len(p) >= 2 and p[1] == "*":
return self.isMatch(s, p[2:]) or first and self.isMatch(s[1:], p)
else:
return first and self.isMatch(s[1:], p[1:])
调试结果:
2.动态规划算法
已知 dp[i-1][j-1]
的状态,分三种情况讨论来确定 dp[i][j]
1.s[i] == p[j] or p[j] == '.'
直接对应字符相等:aabb
和 aabb
或者 cabb
和 cab.
,则dp[i][j] = dp[i-1][j-1] = True
。
2.p[j] == '*'
:*
与前面的字符相关,因此比较星号前的字符 p[j-1]
和 s[i]
的关系。
-
p[j-1] != s[i]
:*
未匹配其前面的字符,应忽略这两个字符。dp[i][j] = dp[i][j-2]
。 -
p[j-1] == s[i] or p[j-1] == '.'
:*
匹配前面的字符 0 个,如b
和bb*
,或者匹配多个ab
和ab.*
,则dp[i][j] = dp[i][j-2]
;当匹配多个时,如aabbb
和aab*
,或者cddddd
和c.*
,则即dp[i][j] = dp[i-1][j]
-
不匹配,则
dp[i][j] = False
时间复杂度: O(TP)
T 和 P 分别表示匹配串和模式串的长度
class Solution:
def isMatch(self, s: str, p: str) -> bool:
# 边界条件
if not p:
return not s
if not s and len(p) == 1:
return False
# 初始状态
m, n = len(s) + 1, len(p) + 1
dp = [[False for x in range(n)] for x in range(m)]
dp[0][0] = True
dp[0][1] = False
for b in range(2, n):
j = b - 1
if p[j] == '*':
dp[0][b] = dp[0][b - 2]
for a in range(1,m):
i = a - 1
for b in range(1, n):
j = b - 1
if s[i] == p[j] or p[j] == '.':
dp[a][b] = dp[a - 1][b - 1]
# p[j]==*前面的字符匹配s[i] 或者是'.'
elif p[j] == '*':
if p[j - 1] == s[i] or p[j - 1] == '.':
dp[a][b] = dp[a - 1][b] or dp[a][b - 2]
else:
dp[a][b] = dp[a][b - 2]
# 情况3
else:
dp[a][b] = False
return dp[m - 1][n - 1]
调试结果: