10.正则表达式匹配
原题链接:https://leetcode-cn.com/problems/regular-expression-matching/。
给定一个字符串 (s) 和一个字符模式 §。实现支持 ‘.’ 和 ‘*’ 的正则表达式匹配。
‘.’ 匹配任意单个字符。
‘*’ 匹配零个或多个前面的元素。
这个问题可以使用使用导入的re包,来进行正则表达式匹配,但是这样除了熟悉一下re包的使用,好像并没有什么用,那么我们先熟悉一下re包的使用。
import re
class Solution(object):
def isMatch(self,s,p):
value = re.match(p,s)
if value == None or value.group(0) != s:
return False
else:
return True
正确的姿势应该是使用动态规划。
首先我们建立一个动态规划表。
dp[i][j]的值表示前j的子模式,和前i的字符子串是否匹配。
假设现在我们有模式:p = Pxy
字符串:s = Sz
接下来我们考虑初始情况,如果模式为空,字符串也为空,那么必然是匹配的。
所以我们有: dp[i][j] = True
然后我们考虑如果字符串不为空,模式为空,那么必然是不匹配的。
那么就有:if j == 0 && i > 0 : dp[i][j] = False
接下来考虑字符串为空,模式不为空。因为’.‘不匹配空字符,
∗
*
∗是可以匹配空字符的。所以只有在出现
∗
*
∗才会有可能出现匹配的情况。
if i0 & y’*’:dp[i][j] = dp[i][j-2]
然后我们开始分析递归式:
现在我们考虑问题dp[i][j],p[j]= y,s[i] = z。
- 如果y == ‘*’;
*那么我们就应该考虑,x和z的情况,如果x和z不匹配。
我们就应该考虑问题dp[i][j-2],也就是说P和Sz是不是匹配。
如果x和z匹配,就会有xz,或者x’.‘:
现在就应该考虑多个问题了,P 和 S 或 Px 和 S 或 P 和 Sz 或 Pxy 和 S 或 Px 和 Sz
其实在y == '’, x == z时,这些问题可以简化。
Px & Sz | P & S | Px & S | Pxy & S 可以简化为一个问题。
可以简化为两个问题:dp[i][i-2] | dp[i-1][j] - 如果y != ‘*’;
- 那么我们就应该考虑问题dp[i-1][j-1],以及y和z是否匹配。
class Solution(object):
def isMatch(self, s,p):
m = len(s)
n = len(p)
dp = [[False]*(n+1) for _ in range(m+1)]
dp[0][0] = True
for i in range(m+1):
for j in range(1,n+1):
if p[j-1] == '*':
dp[i][j] = dp[i][j-2] or \
(i>0 and (dp[i-1][j]) and (s[i-1] == p[j-2] or p[j-2] == '.'))
else:
dp[i][j] = i>0 and (dp[i-1][j-1] and (s[i-1] == p[j-1] or p[j-1]=='.'))
return dp[m][n]
44.通配符匹配
原题链接:https://leetcode-cn.com/problems/wildcard-matching/.
给定一个字符串 (s) 和一个字符模式 § ,实现一个支持 ‘?’ 和 ‘*’ 的通配符匹配。
‘?’ 可以匹配任何单个字符。
‘*’ 可以匹配任意字符串(包括空字符串)。
两个字符串完全匹配才算匹配成功。
这个问题和上一个问题,很类似。
同上建立一个动态规划表,dp[i][j],定义与上一道题目相同。
现在我们有模式p = Px;
字符串s = Sy;
考虑初始问题,dp[0][0] = True.
当字符串为空,模式不为空,如果p[j] = ‘*’,那么我们有dp[i][j] = dp[i][j-1].
构造递归解:
对于问题dp[i][j].
- 如果p[j] == ‘*’ ,我们考虑问题P & S | Px & S | P & Sy. P & S ,Px & S 简化为一个问题。所以有:
- if p[j] == ‘*’: dp[i][j] = dp[i][j-1] | dp[i-1][j]
- 如果p[j] != ‘*’,我们就应该考虑 (P & S) & x 和 y是否匹配。 所以就有:
- if p[j] != ‘*’ : dp[i][j] = dp[i-1][j-1] & (p[j] == s[i] \ p[i] == ‘?’)
class Soultion(object):
def isMatch(self,s, p):
n = len(s)
m = len(p)
dp = [[False]*(m+1) for _ in range(n+1)]
dp[0][0] = True
for i in range(n+1):
for j in range(m+1):
if p[j-1] == '*':
if i == 0:
dp[i][j] = dp[i][j-1]
else:
dp[i][j] = dp[i-1][j-1] and (s[i-1] == p[j-1] or p[j-1] == '?')
return dp[n][m]