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)