題目: 正則表示匹配
Given an input string (
s
) and a pattern (p
), implement regular expression matching with support for'.'
and'*'
.'.' Matches any single character. '*' Matches zero or more of the preceding element.
示例:
Input1: s = "aa" p = "a" Output1: false Explanation: "a" does not match the entire string "aa".Input2: s = "aa" p = "a*" Output2: true Explanation: '*' means zero or more of the precedeng element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".Input3: s = "ab" p = ".*" Output3: true Explanation: ".*" means "zero or more (*) of any character (.)".Input4: s = "aab" p = "c*a*b" Output4: true Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore it matches "aab".Input5: s = "mississippi" p = "mis*is*p*." Output5: false
首先在題目理解上,與之前的題(劍指offer)上的不同,“.* " 表示意義上可爲任意數,而不一定是單一個數重複,見 input3。
其次,我們分析題意,可以分成以下幾種情況:
1. s 爲空,且p爲空,表示同時結束,return True;
2. s爲空,但p不爲空,若想匹配成功,p必然爲 “x*” 這類組合,*表示字符 x 個數爲0;
3. s不爲空,p爲空,必然匹配不成功, return False;
4. s不爲空,p不爲空:
如果p[1] 不等於 “*”,看p[0]和s[0]是否匹配,如果字符相等,或p[0]爲 “.”,則後移繼續匹配,否則返回False;
如果p[1] 等於 "*", 則表示p[0]可以有0-N個,情況更爲複雜一些,還需要看 p[0] 和 s[0] 是否匹配,若不匹配,必爲0個,則 p 後移兩位; 如果匹配,則說明當前s[0] 匹配成功,將s後移一位,剩餘的繼續判斷。
上述邏輯,就是簡單的遞歸,在寫代碼時,注意精簡即可:
class Solution(object):
def isMatch(self, s, p):
"""
:type s: str
:type p: str
:rtype: bool
"""
if not p:
return not s
first_match = bool(s) and p[0] in {"." , s[0]}
if len(p)>=2 and p[1]=="*":
return self.isMatch(s,p[2:]) or first_match and self.isMatch(s[1:],p)
else:
return first_match and self.isMatch(s[1:],p[1:])
遞歸方法十分耗時(≈1460ms),所以我們進一步考慮使用動態規劃,以空間換時間。思路是一樣的,增加了二維數組,存儲已經計算的變量,從而極大減少了時間(時間 36 ms)。
class Solution(object):
def isMatch(self, s, p):
"""
:type s: str
:type p: str
:rtype: bool
"""
saved = {}
def dp(i,j):
if (i,j) not in saved:
if j == len(p):
ans = (i == len(s))
else:
first_match = i <len(s) and p[j] in {".",s[i]}
if j+1 < len(p) and p[j+1] =="*":
ans = dp(i,j+2) or first_match and dp(i+1,j)
else:
ans = first_match and dp(i+1,j+1)
saved[i,j] = ans
return saved[i,j]
return dp(0,0)
小結:
本題主要難點在理清題目的主要思路,用最精簡的方式寫出代碼。動態規劃與遞歸方法都是基於題目的基本理解。