LeetCode 44. 通配符匹配 | Python

44. 通配符匹配


題目來源:力扣(LeetCode)https://leetcode-cn.com/problems/wildcard-matchingpython

題目


給定一個字符串 (s) 和一個字符模式 (p) ,實現一個支持 '?' 和 '*' 的通配符匹配。正則表達式

'?' 能夠匹配任何單個字符。
'*' 能夠匹配任意字符串(包括空字符串)。
兩個字符串徹底匹配纔算匹配成功。

說明:express

  • s 可能爲空,且只包含從 a-z 的小寫字母。
  • p 可能爲空,且只包含從 a-z 的小寫字母,以及字符 ? 和 *。

示例 1:bash

輸入:
s = "aa"
p = "a"
輸出: false
解釋: "a" 沒法匹配 "aa" 整個字符串。

示例 2:微信

輸入:
s = "aa"
p = "*"
輸出: true
解釋: '*' 能夠匹配任意字符串。

示例 3:.net

輸入:
s = "cb"
p = "?a"
輸出: false
解釋: '?' 能夠匹配 'c', 但第二個 'a' 沒法匹配 'b'。

示例 4:code

輸入:
s = "adceb"
p = "*a*b"
輸出: true
解釋: 第一個 '*' 能夠匹配空字符串, 第二個 '*' 能夠匹配字符串 "dce".

示例 5:blog

輸入:
s = "acdcb"
p = "a*c?b"
輸出: false

解題思路


思路:動態規劃leetcode

這道題,跟 10. 正則表達式匹配 有點相似。關於 【10. 正則表達式匹配】 的題解,可經過下面的連接進行閱讀了解:字符串

LeetCode 10. 正則表達式匹配 | Python

不過這裏兩題當中有點不同的地方。【10. 正則表達式匹配】 此題的字符模式 p 的字符並非單獨的,例如:.* 二者關聯會造成新的匹配模式。而本題中,p 的字符是獨立的,並不會與先後產生關聯。

先看題目說明,其中字符模式 p,出現的狀況有如下幾種:

  • a-z 的小寫字母,這裏就僅對應相應的小寫字母
  • ?,可以匹配任意單個字符(也便是任何一個字母)
  • *,匹配任意字符串(包括空字符串,也便是可以匹配 0 個或多個字符)

本題使用 動態規劃 的解法,先定義狀態,用 dp[i][j] 表示 s 的前 i 個字符串和模式 p 的前 j 個字符串是否匹配。那麼進行狀態轉移的時候,會遇到下面的狀況:

  • 若是 p[j-1] == s[i-1] 或者 p[j-1] == '?' 的時候,表示當前第 i 個字符是匹配的,那麼 dp[i][j] 能夠由 dp[i-1][j-1] 轉換而來。
  • 若是 p[j-1] == '*' 時,表示當前能夠匹配 0 個字符或者多個字符。那麼 dp[i][j] 能夠由 dp[i][j-1] 或者 dp[i-1][j] 轉移而來。具體狀況以下:
    • 當使用星號匹配時,dp[i][j] 能夠由 dp[i-1][j] 轉移而來
    • 當不使用星號匹配時,dp[i][j] 能夠由 dp[i][j-1] 轉移而來

因此,狀態轉移方程以下:

狀態轉移方程

如今開始進行初始化,不過這裏須要注意邊界的問題:

  • 初始化 dp[0][0]=True,表示當字符串 s 和字符模式 p 都爲空,表示可以匹配;
  • dp[i][0] 表示字符模式 p 爲空,沒法匹配非空字符串,這裏必定爲 False;(初始 dp 爲 False)
  • dp[0][j] 這裏表示字符模式 p 不爲空,匹配空字符串。在這裏,只有字符模式前 j 個字符都星號 * 纔可以成立,因此一樣要單獨分狀況進行初始化。

具體的代碼實現以下。

代碼實現


class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        s_length = len(s)
        p_length = len(p)

        # 初始化 dp
        dp = [[False] * (p_length+1) for _ in range(s_length + 1)]

        # 初始化 dp[0][0],表示空模式匹配空字符串
        dp[0][0] = True

        # 初始化 dp[0][j],非空模式匹配空字符串
        for j in range(1, p_length+1):
            if p[j-1] != "*":
                break
            dp[0][j] = True
        
        for i in range(1, s_length+1):
            for j in range(1, p_length+1):
                # 代入轉移方程
                if p[j-1] == s[i-1] or p[j-1] == "?":
                    dp[i][j] = dp[i-1][j-1]
                elif p[j-1] == "*":
                    dp[i][j] = dp[i-1][j] or dp[i][j-1]
        
        return dp[s_length][p_length]

實現結果


實現結果


文章原創,歡迎關注點贊。微信公衆號《書所集錄》同步更新,一樣歡迎關注。

qrcode_for_Demon

相關文章
相關標籤/搜索