引言
核心的dp状态设计还是老方法,但是给出了通配符这个新东西。因此要对这类操作有新的思考。
其中涉及到了一个状态压缩的方法比较巧妙。
题目
思考,状态还是自然定义为
dp[i][j]
,表示
s[:i]
和
p[:j]
匹配的情况。对于状态的转移我们考虑两种大的情况:
-
这是一个特殊的情况,我们需要整体处理p[j+1] == '*'
这种形式a*
-
此时是匹配的,可以化为s[i] == p[j] or '.'
dp[i][j] = dp[i-1][j-1]
- 当
p = '*'
,需要看前一个字符的匹配情况,
(1)能匹配正确,此时枚举能需要重复几次,1次:
, 两次:dp[i-1][j-2] and s[i] == p[j-1]
dp[i-2][j-2] and s[i-1] == p[j-2] and s[i] == p[j-2]
…
(2)无法匹配上,此时让前一个字符消失
dp[i][j-2]
- 当
有情况p = '*'
一次是重复0次,重复一次,重复两次。。。dp[i][j] = dp[i][j-2] or (dp[i-1][j-2] and p[j-1]==s[i]) or (dp[i-2][j-2] and p[j-1]==s[i] and p[j-1] == s[i-1].....
状态压缩:
对比前后两个状态
6.
dp[i][j] = dp[i][j-2] or (dp[i-1][j-2] and p[j-1]==s[i]) or (dp[i-2][j-2] and p[j-1]==s[i] and p[j-1] == s[i-1].....
7.
dp[i-1][j] = dp[i-1][j-2] or (dp[i-2][j-2] and p[j-1]==s[i-1]) ....
可以很明显的看出
dp[i][j] = (dp[i-1][j] and p[j-1]==s[i]) or dp[i][j-2]
还需要特别处理,边界的代码,保证保证"a"可以匹配""空*
因此得到代码:
class Solution:
def isMatch(self, s: str, p: str) -> bool:
n = len(s)
m = len(p)
dp = [[False]*(m+1) for _ in range(n+1)]
# 为了在索引上进行匹配
s = ' '+s
p = ' '+p
dp[0][0] = True
# 预处理,保证"a*"可以匹配""空
for j in range(2, m + 1):
dp[0][j] = dp[0][j - 2] and p[j] == '*'
for i in range(1, n + 1):
for j in range(1, m + 1):
if p[j] == '*':
if s[i] == p[j - 1] or p[j - 1] == '.':
dp[i][j] = dp[i][j - 2] or dp[i - 1][j]
else: dp[i][j] = dp[i][j - 2]
elif s[i] == p[j] or p[j] == '.':
dp[i][j] = dp[i - 1][j - 1]
return dp[n][m]
例题2:通配符匹配
与正则表达式匹配类似的题目,需要考虑如何处理两个特殊的匹配符号。
- 对于
很容易处理,可以当成替换操作,只需要?
dp[i][j] = dp[i-1][j-1]
- 对于
就需要特殊处理,我们可以视为一个删除(匹配空)操作*
或者添加(表示当前星号匹配了当前的位置的字符)操作dp[i][j-1]
,dp[i][j] = dp[i-1][j]
dp[i][j] = dp[i][j-1] or dp[i-1][j]
另外需要注意边界的处理,
***
也是可以匹配空字符串的。
class Solution:
def isMatch(self, s: str, p: str) -> bool:
n = len(s)
m = len(p)
dp = [[False]*(m+1) for _ in range(n+1)]
dp[0][0] = True
# 考虑边界的特殊情况,"*"是可以匹配空的
for i in range(1, m+1):
if p[i-1] == '*':
dp[0][i] = True
else:
break
for i in range(1,n+1):
for j in range(1,m+1):
if p[j-1] == '*':
# 匹配当前,或空匹配
dp[i][j] = dp[i-1][j] | dp[i][j-1]
elif p[j-1] == '?' or p[j-1] == s[i-1]:
dp[i][j] = dp[i-1][j-1]
return dp[n][m]