10 正则表达式匹配 https://leetcode-cn.com/problems/regular-expression-matching/
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。 '.' 匹配任意 单个字符 '*' 匹配 零个或多个前面的那一个元素 所谓匹配,是要涵盖整个字符串 s的,而不是部分字符串。 说明: s 可能为空,且只包含从 a-z 的小写字母。 p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 * 示例 1: 输入: s = "aa" p = "a" 输出: false 解释: "a" 无法匹配 "aa" 整个字符串。 示例 2: 输入: s = "aa" p = "a*" 输出: true 解释: 因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。 示例 3: 输入: s = "ab" p = ".*" 输出: true 解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。 示例 4: 输入: s = "aab" p = "c*a*b" 输出: true 解释: 因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。 示例 5: 输入: s = "mississippi" p = "mis*is*p*." 输出: false
思路:
dp[i][j] 表示 s 的前 i 个是否能被 p 的前 j个匹配
p[j] == s[i] or p[j]=='.' : dp[i][j] = dp[i-1][j-1] 然后从 p[j] 可能的情况来考虑,让 p[j]=各种能等于的东西。 p[j] ==" * ": 1. p[j-1] != s[i] : dp[i][j] = dp[i][j-2]
2. p[j-1] == s[i] or p[j-1] == ".": dp[r][c] = dp[r - 1][c] or dp[r][c - 2]
class Solution:
def isMatch(self, s: str, p: str) -> bool:
if not p: return not s
nrow = len(s) + 1
ncol = len(p) + 1
# dp 第一行、第一列 没有意义,只是作为递归的初始
dp = [[False for c in range(ncol)] for r in range(nrow)]
dp[0][0] = True
# 在 dp[r][c] 矩阵中, 一定要保证初始的 dp[0][0]=T, 以进行后续的递归,
# 而 1,3... = *时,此时的 dp[0][c-2] == dp[0][0] = T
for c in range(1, ncol-1):
if p[c] == '*':
dp[0][c+1] = dp[0][c - 1]
for r in range(1, nrow):
i = r - 1
for c in range(1, ncol):
j = c - 1
# 只是 计算满足情况的条件
if s[i] == p[j] or p[j] == '.':
dp[r][c] = dp[r - 1][c - 1] # 同时推进
elif p[j] == '*':
if p[j - 1] == s[i] or p[j - 1] == '.' :
# 保证 p的前一位 = s, 此时可以是2种情况,
# *=1 -- dp[r-1][c], *=0 -- dp[r][c-2]
dp[r][c] = dp[r - 1][c] or dp[r][c - 2]
else:
# p 的前一位 != s, *=0 , 取 dp[r][c-2] 位值
dp[r][c] = dp[r][c - 2]
return dp[- 1][- 1]
if __name__ == "__main__":
s = "aab"
p = "c*a*b"
ss = Solution()
r = ss.isMatch(s,p)
print(r)