Leetcode 44:萬用字元匹配(超詳細的解法!!!)
阿新 • • 發佈:2018-11-19
給定一個字串 (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
解題思路
這個問題和之前問題Leetcode 10:正則表示式匹配(最詳細的解法!!!)很類似,而且比之前的問題要容易,我們只要在之前問題上稍加修改就可以了。我們稍微說一下這個問題的思路,這個問題的難點在於判斷*
p
的第一個元素是不是*
。如果p
的第一個元素是*
的話,那我們只要考慮*
是匹配零次還是匹配一次即可,也就是我們只要判斷isMatch(s[1:],p)
和isMatch(s,p[1:])
。
如果p
的第一個元素不是*
的話,我們只要判斷s[0]
與p[0]
能否匹配。所以我們可以非常迅速的寫出動態規劃轉移方程。
f(i,j)
表示輸入s[0:i]
和輸入p[0:j]
時的匹配結果。具體的思維轉換過程可以閱讀之前的文章。
class Solution:
def isMatch(self, s, p):
"""
:type s: str
:type p: str
:rtype: bool
"""
s_len, p_len = len(s), len(p)
mem = [[False]*(p_len + 1) for _ in range(s_len + 1)]
mem[0][0] = True
for i in range(s_len + 1):
for j in range(1, p_len + 1):
if p[j-1] == '*':
mem[i][j] = mem[i][j-1] or \
(i > 0 and mem[i-1][j])
else:
mem[i][j] = i > 0 and\
mem[i-1][j-1] and \
(s[i-1] == p[j-1] or p[j-1] == "?")
return mem[-1][-1]
由於這個問題比較簡單,所以我們可以直接從正面去解決它。我們先遍歷s
和p
s: a d c e b
i
p: * a * b
j
我們發現j
指向的元素是*
,所以我們記錄下*
的位置和此時i
的位置,然後我們j++
判斷下一個位置。
s: a d c e b
i
p: * a * b
j
star:0
i_index:0
接著我們判斷i
和j
所指向的元素是不是相同,如果是的話我們i++;j++
。
s: a d c e b
i
p: * a * b
j
star:0
i_index:0
此時j
所指向的元素又是*
,我們按之前那樣操作。
s: a d c e b
i
p: * a * b
j
star:2
i_index:1
此時,我們發現j
既沒有指向*
,i
和j
所指向的元素又不相等。我們要回過頭來看*
,我們此時是知道*
的位置的,所以我們直接i++
即可,也就是*
此時匹配兩次。
s: a d c e b
i
p: * a * b
j
star:2
i_index:1
同上,我們再令i++
。
s: a d c e b
i
p: * a * b
j
star:2
i_index:1
此時,我們發現i
和j
所指向的元素相同,所以我們i++;j++
,此時我們發現匹配結束了,並且匹配成功。
我們回顧一下上面的整個過程,這其中還有一些漏洞,首先如果上述三種情況都不存在,那麼我們直接返回false
。如果我們匹配結束後(s
匹配完),我們發現j
所指向的元素以及其後的所有元素是*
以外的元素話,我們返回false
。
class Solution:
def isMatch(self, s, p):
"""
:type s: str
:type p: str
:rtype: bool
"""
s_len, p_len = len(s), len(p)
i, j, star, i_index = 0, 0, -1, 0
while i < s_len:
if j < p_len and (p[j] == '?' or p[j] == s[i]):
i += 1
j += 1
elif j < p_len and p[j] == '*':
star = j
j += 1
i_index = i
elif star != -1:
j = star + 1
i_index += 1
i = i_index
else:
return False
while j < p_len and p[j] == '*':
j += 1
return j == p_len
reference:
我將該問題的其他語言版本新增到了我的GitHub Leetcode
如有問題,希望大家指出!!!