class Solution:
def isMatch(self, s: str, p: str) -> bool:
i = 0
j = 0
while i < len(s) and j < len(p):
if s[i] == p[j] or p[j] == '.':
i += 1
j += 1
else:
return False
return i == j
接下來要考慮的是如果有 * 的情況。
因為星號會出現在下一個位置,所以我們要看的是 p[j+1] 的情況。並且要小心的處理邊界。
接下來要考慮的情況分成
當 s[i] == p[j] or p[j] == '.' :
p[j+1] != '*' 兩個指針往前走。
p[j+1] == '*' 可以匹配零到多個字元,例如匹配零個字元:s = "aa", p = "a*aa" 匹配多個字元:s = "aaa", p = "a*" 。
當 s[i] != p[j] :
p[j+1] != '*'不匹配,回傳 False
p[j+1] == '*' 只能匹配零個字元,例如:s = "cc", p = "ca*c" 。
分析到這裡,最困難的就是 1-2 到底要怎麼選擇,到底要不要匹配字元,於是我們可以改寫
class Solution:
def isMatch(self, s: str, p: str) -> bool:
memo = {}
def dp(i, j):
res = False
if s[i] == p[j] or p[j] == '.':
if j < len(p) - 1 and p[j + 1] == '*':
# dp 匹配多次 or 一次都不要匹配
res = dp(i + 1, j) or dp(i, j + 2)
else:
res = dp(i + 1, j + 1)
else:
if j < len(p) - 1 and p[j + 1] == '*':
res = dp(i, j + 2)
else:
res = False
memo[(i, j)] = res
return memo[(i, j)]
return dp(0, 0)
可是到了這一步還沒有結束,因為我們要知道 Base case 的終止條件。
第一個終止條件很簡單,那就是 j 指針指向 p 的終點的時候,i 剛好也在 s 的終點。
if j == len(p):
return i == len(s)
可是當 i 在 s 的終點的時候不能只是簡單的判斷 j 是不是也在終點,例如:p 在 j 位置之後是一連串的 a*b*c*d*a*c*... 這樣的字串。這些判斷是都可以是作為空字串的判斷。