[H]O-19 正则表达式匹配
题目
请实现一个函数用来匹配包含’. ‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"ab*a"均不匹配。
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母以及字符 . 和 *,无连续的 *。
输入:
s = "ab"
p = ".*"
输出: true
解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。
示例 4:
输入:
s = "aab"
p = "c*a*b"
输出: true
解释: 因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。
示例 5:
输入:
s = "mississippi"
p = "mis*is*p*."
输出: false
解决方法:动态规划
设 ss 的长度为 nn , pp 的长度为 mm ;将 ss 的第 ii 个字符记为 s_i,pp 的第 j个字符记为 p_j ,将 ss 的前 i个字符组成的子字符串记为 s[:i] , 同理将 pp 的前 j个字符组成的子字符串记为 p[:j]。
因此,本题可转化为求 s[:n] 是否能和 p[:m] 匹配
总体思路是从 s[:1] 和 p[:1] 是否能匹配开始判断,每轮添加一个字符并判断是否能匹配,直至添加完整个字符串 s 和 p。
本题的状态共有 n×m 种,应定义状态矩阵dp ,dp[i][j] 代表 s[:i] 与 p[:j] 是否可以匹配。
做好状态定义,接下来就是根据 「普通字符」 , 「.」 , 「*」三种字符的功能定义,分析出动态规划的转移方程。
1.初始化
当s,p均为空时,匹配——dp[0][0]=True
当s非空,p为空,不可能匹配。
当s是空串,p不是的时候,如下才可:(满足偶数位为*才有可能)
2.返回值
dp 矩阵右下角字符,代表字符串 s 和 p 能否匹配。
3.当s,p均非空时,遍历
状态定义: 设动态规划矩阵 dp , dp[i][j] 代表字符串 s 的前 i 个字符和 p 的前 j 个字符能否匹配。
转移方程: 需要注意,由于 dp[0][0] 代表的是空字符的状态, 因此 dp[i][j] 对应的添加字符是 s[i - 1] 和 p[j - 1] 。
当 p[j - 1] = ‘*’ 时, dp[i][j] 在当以下任一情况为 true 时等于 true :
- dp[i][j - 2]: 即将字符组合 p[j - 2] * 看作出现 0 次时,能否匹配;
(如a和ab*)
- dp[i][j - 1]: 即将字符组合 p[j - 2] * 看作出现 1 次时,能否匹配;
(如ab和ab*)
- dp[i - 1][j] 且 s[i - 1] = p[j - 2]: 即让字符 p[j - 2] 多出现 1 次时,能否匹配;
(如abb和ab*)
- dp[i - 1][j] 且 p[j - 2] = ‘.’: 即让字符 ‘.’ 多出现 1 次时,能否匹配;
(如abb和a.*)
当 p[j - 1] != ‘*’ 时, dp[i][j] 在当以下任一情况为true 时等于 true :
- dp[i - 1][j - 1] 且 s[i - 1] = p[j - 1]: 即让字符 p[j - 1] 多出现一次时,能否匹配;
(abc和abc)
- dp[i - 1][j - 1] 且 p[j - 1] = ‘.’: 即将字符 . 看作字符 s[i - 1] 时,能否匹配;
(abc和ab.)
python代码
class Solution:
def isMatch(self, s: str, p: str) -> bool:
n,m=len(s)+1,len(p)+1
dp=[[False]*m for _ in range(n)]
dp[0][0]=True
for i in range(2,m,2):
dp[0][i]=dp[0][i-2] and p[i-1]=='*'
for i in range(1,n):
for j in range(1,m):
if p[j-1]!='*':
if dp[i - 1][j - 1] and s[i - 1] == p[j - 1]: dp[i][j] = True # 5.
elif dp[i - 1][j - 1] and p[j - 1] == '.': dp[i][j] = True # 6.
else:
#1,2
if dp[i][j-2] or dp[i][j-1]: dp[i][j]= True
#3
if dp[i-1][j] and s[i-1]==p[j-2]: dp[i][j]=True
#4
if dp[i-2][j] and p[j-2]=='.': dp[i][j]=True
return dp[-1][-1]
-----2021/1.8遇到的第一道hard,这个动态规划好厉害。。。糊里糊涂.jpg-------