1. 程式人生 > >python leetcode 044 萬用字元匹配(困難)解題報告

python leetcode 044 萬用字元匹配(困難)解題報告

給定一個字串 (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位也完全匹配。