請實現一個函數用來匹配包含’. ‘和’‘的正則表達式。模式中的字符’.‘表示任意一個字符,而’'表示它前面的字符可以出現任意次(含0次)。在本題中,匹配是指字符串的所有字符匹配整個模式。例如,字符串"aaa"與模式"a.a"和"abaca"匹配,但與"aa.a"和"ab*a"均不匹配。
示例 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 = “cab”
輸出: true
解釋: 因爲 ‘*’ 表示零個或多個,這裏 ‘c’ 爲 0 個, ‘a’ 被重複一次。因此可以匹配字符串 “aab”。
示例 5:
輸入:
s = “mississippi”
p = “misisp*.”
輸出: false
s 可能爲空,且只包含從 a-z 的小寫字母。
p 可能爲空,且只包含從 a-z 的小寫字母,以及字符 . 和 *。
注意:本題與主站 10 題相同:https://leetcode-cn.com/problems/regular-expression-matching/
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/zheng-ze-biao-da-shi-pi-pei-lcof
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
思路1:遞規
這題的類別是Difficult級別的,初看確實有的不好考慮,特別是剛開始準備純靠邏輯判斷來做,發現後面情況太多,單純判斷不好做。於是看了題解,一堆用dp和遞歸來做了。但是dp的看了需求還是有的地方沒太懂,於是自己用遞歸做出來了。想到用遞歸後思路其實很清晰,就是有的需要考慮的很全面才行。
具體的細節可以看代碼。
個人認爲dp其實就是遞推,它其實就是和遞歸相反,它是從正面推算,而遞歸這較爲簡單,它是從後往前算。
- 第一份代碼我假設了一個字符串中不會出現的字符#,加在需要判單字符串的開頭,這樣就避免判空的過程。
- 第二份代碼具備了一般性
class Solution:
def isMatch(self, s: str, p: str) -> bool:
def match(s, p) ->bool:
if s == p:
return True
if s == '' or p == '':
return False
if s[-1] == p[-1] or (p[-1] == '.' and s[-1] != '#'):
return match(s[:-1], p[:-1])
if p[-1] == '*':
if len(p)>=2:
if p[-2] == s[-1] or (p[-2] == '.' and s[-1] != '#'):
# *匹配0個、一個或者多個
return match(s, p[:-2]) or match(s[:-1], p[:-2]) or match(s[:-1], p)
else:
# 不能匹配
return match(s, p[:-2])
return False
# 遞歸解法
return match('#'+s, '#'+p)
class Solution:
def isMatch(self, s: str, p: str) -> bool:
def match(s, p) ->bool:
if s == p:
return True
if s != '' and p == '':
return False
elif s == '' and p != '':
if p[-1] == '*':
if len(p)>=2:
return match(s, p[:-2])
return False
else:
if s[-1] == p[-1] or p[-1] == '.':
return match(s[:-1], p[:-1])
if p[-1] == '*':
if len(p)>=2:
if p[-2] == s[-1] or p[-2] == '.':
# *匹配0個、一個或者多個
return match(s, p[:-2]) or match(s[:-1], p[:-2]) or match(s[:-1], p)
else:
# 不能匹配
return match(s, p[:-2])
return False
# 遞歸解法
return match(s, p)
思路2: 動態規劃(dp)
class Solution:
def isMatch(self, s: str, p: str) -> bool:
length_n = len(s)
length_p = len(p)
dp = [[False] * (length_p+1) for _ in range(length_n+1)]
for i in range(length_n+1):
for j in range(length_p+1):
# 分成空正則和非空正則兩種
if j == 0:
dp[i][j] = i == 0
else:
# 按照p[j]進行討論
if p[j-1] == '*':
# 不看x*
if j >= 2:
dp[i][j] |= dp[i][j-2]
# 看
if i >= 1 and (s[i-1] == p[j-2] or p[j-2] == '.'):
dp[i][j] |= dp[i-1][j]
elif i > 0 and (p[j-1] == '.' or p[j-1] == s[i-1]):
dp[i][j] = dp[i-1][j-1]
return dp[length_n][length_p]