python leetcode 044 萬用字元匹配(困難)解題報告
阿新 • • 發佈:2019-02-01
給定一個字串 (s
) 和一個字元模式 (p
) ,實現一個支援 '?'
和 '*'
的萬用字元匹配。
'?' 可以匹配任何單個字元。 '*' 可以匹配任意字串(包括空字串)。
兩個字串完全匹配才算匹配成功。
說明:
s
可能為空,且只包含從a-z
的小寫字母。p
可能為空,且只包含從a-z
的小寫字母,以及字元?
和*
。
示例 1:
輸入: s = "aa" p = "a" 輸出: false 解釋: "a" 無法匹配 "aa" 整個字串。
示例 2:
輸入: s = "aa" p = "*" 輸出: true 解釋: '*' 可以匹配任意字串。
示例 3:
輸入: s = "cb" p = "?a" 輸出:false 解釋: '?' 可以匹配 'c', 但第二個 'a' 無法匹配 'b'。
示例 4:
輸入: s = "adceb" p = "*a*b" 輸出: true 解釋: 第一個 '*' 可以匹配空字串, 第二個 '*' 可以匹配字串 "dce".
示例 5:
輸入: s = "acdcb" p = "a*c?b" 輸入: false
題目意思:大概類似於Re那道題的匹配。‘*'比較牛逼,可以想匹配啥就匹配啥,而'?'就不太一樣,只能匹配單個字元(字串也不允許)。很明顯這道題是要用動態規劃的。
思路:對於這種字串+動態規劃的題,題目問的是s和p是否匹配,我們應該把它認為是s的前len(s)個字元與p的前len(p)個字元是否匹配。這是一種對問題的不同層次的看法,用動態發展的眼光去看。既然動態規劃,最難的就是研究動態轉移方程,接下來剖析一下。
dp[i][j]表示p的前i個字元與s的前j個字元是否匹配。
class Solution: def isMatch(self, s, p): """ :type s: str :type p: str :rtype: bool """ #dp表,很常規,以p字串作為列,以s作為行 dp = [[False for i in range(len(p)+1)] for j in range(len(s)+1)] #雙方都是空字串,當然是true dp[0][0] = True for i in range(1, len(p)+1): if p[i-1] == '*': dp[0][i] = dp[0][i-1] #探討的是當s為空字串時,p的前j項是否匹配 #如果p的這一次對應的項是*,則看它前一項是否匹配,如果是其他,抱歉,還是false #我們沒有去填s不為空,p為空的情況,因為這樣會剛好符合預設,也就是全為false。 #開始填dp表 #把字串想象成未完成的狀態,因為動態規劃本身其實是不斷在建設字串的,所以p[j-1]為p的最後一項,因為後面的還未建設 for i in range(1, len(s)+1): for j in range(1, len(p)+1): #如果我們最後一項為* if p[j-1] == '*': #第一,有可能它代表空字串 #第二,有可能它就代表一個字串,也就是對應的那個 #第三,有可能它代表多個字元 dp[i][j] = dp[i][j-1] or dp[i-1][j-1] or dp[i-1][j] else: #如果我們這一項為其他的,有可能是字母或'?' #必須要求各後退一項也能匹配,並且在這號位上也能匹配 dp[i][j] = (s[i-1] == p[j-1] or p[j-1] == '?') and dp[i-1][j-1] #返回前len(s)的s 與 前len(p)的匹對結果 return dp[len(s)][len(p)]
字串動規匹配總結:
建設中的最後一項指的是p[j-1],就我們這道題而言,它是不斷在變大的,是動態的
1.如果建設中的最後一項為可以任意代表的比如*,則想象它代表空,代表一個字元,代表多個字元。
2.如果建設中的最後一項為單個字元的,則要求當前這一位匹配,且前i-1與j-1位也完全匹配。