給你乙個字串 s 和乙個字元規律 p,請你來實現乙個支援 『.』 和 『*』 的正規表示式匹配。
『.』 匹配任意單個字元『*』 匹配零個或多個前面的那乙個元素
所謂匹配,是要涵蓋整個字串 s 的,而
是部分字串。
輸入:s = 「aa」 p = 「a」輸出:false
解釋:「a」 無法匹配 「aa」 整個字串。
輸入:s = 「aa」 p = 「a*」輸出:true
解釋:因為 『*』 代表可以匹配零個或多個前面的那乙個元素, 在這裡前面的元素就是 『a』。因此,字串 「aa」 可被視為 『a』 重複了一次。
輸入:s = 「ab」 p = 「."輸出:true
解釋:".」 表示可匹配零個或多個(』*』)任意字元(』.』)。
輸入:s = 「aab」 p = 「cab」輸出:true
解釋:因為 『*』 表示零個或多個,這裡 『c』 為 0 個, 『a』 被重複一次。因此可以匹配字串 「aab」。
輸入:s = 「mississippi」 p = 「misisp*.」輸出:false
0 <= s.length <= 200 <= p.length <= 30
s 可能為空,且只包含從 a-z 的小寫字母。
p 可能為空,且只包含從 a-z 的小寫字母,以及字元 . 和 *。
保證每次出現字元 * 時,前面都匹配到有效的字元
第一眼看上去該題要使用動態規劃,接下來將分析具體的思路。首先我們先建立乙個 dp[m + 1][n + 1] 陣列,dp[i][j]表示s[0:i]和p[0:j]是否能夠匹配,m、n分別是字串s和p的長度,之所以要+1是因為要給陣列乙個初始的值,即兩個空串肯定是可以匹配的,dp[0][0] = true.
題目的要求就是兩個字串能夠以一定的規則匹配,其中 s 字串全是英文本元,p字串含有英文本元和兩個符號:『 . 』和『 * 』。
那麼我們可以根據p中字元的種類將整個思路分成三種情況:
p[j] 為普通英文本元這種是最一般的情況,假設此時 s 字串走到了 i 位置,p 字串走到了 j 位置,如下圖:p[j] 為『.』
p[j] 為『 * 』
在上圖示例中,s[0:i] 和 p[0:j]能夠匹配成功有兩個條件:首先必須滿足s[0: i-1]和p[0: j-1]是可以匹配成功的,其次要滿足s[i]和p[j]是匹配成功的。
由此可以得出:
dp[i][j] = dp[i - 1][j - 1] && s[i] == p[j]這種情況其實是上一種情況的特殊版,原因在於:』.『可以匹配任意乙個普通英文本元,兩個重點:「 任意 」 和 「 乙個 」,也就是說,當p[j]為』.『時,無論s[i]為什麼,在題目的規則下,永遠滿足s[i] == p[j]。示例如下:
根據規則,上圖中滿足:』 b 』 == 『.』
由此可以得出:
dp[i][j] = dp[i-1][j-1]這種情況其實是最複雜的情況,』 * '可以代表非負數個前乙個字元,我們並不知道代表多少個,這就是這種情況的複雜之處。·
我們先看上圖的例子:根據肉眼觀察,這時候,『 * 』代表0個前乙個字元,相當於「 a* 」這樣乙個整體相當於乙個""字串,即空字串,相當於把「 a* 」在p字串中消失了。
那麼什麼時候我們要考慮』 * '代表0個前乙個字元呢?
很顯然,如果s[i] 與 p[j-1] 不相等,那麼就說明當前位置下,』 * 『代表0個前乙個字元。即:
s[i] != p[j-1] => dp[i][j] == dp[i][j-2]那麼s[i] == p[j]的時候,就要考慮』 * 『代表非0個前乙個字元的情況了,我們先看乙個極端的例子:
這裡的 』 * 』 代表多個』 e ',由於我們不知道具體代表多少個,那麼這裡我們就假設代表1個,假設的結果是什麼呢?
對,讓 i 左移乙個單位,那麼
dp[i][j] = dp[i - 1][j]。左移之後,會再次遇到這種情況,從而再次左移,最後會出現下面的情況:
這種情況是不是似曾相識?
對,這種情況屬於』 * '代表 0 個前乙個字母的情況,正好就是我們之前講過的s[i] != p[j-1]這種情況。此時:
dp[i][j] = dp[i][j-2]也就是說,無論』 * 『表示多少個前乙個字母的情況,最後都會回到代表0個的情況。
綜上所述,
p[j]是普通字元,則:dp[i][j] = dp[i-1][j-1] && s[i]==p[j]
p[j]是』 . 『,則:
dp[i][j] = dp[i-1][j-1]
p[j]是』 * ',則:
if s[i] == p[j-1]
dp[i][j] = dp[i][j-2] or dp[i-1][j]
if s[i] != p[j-1]
dp[i][j] = dp[i][j-2]
可以寫出下列的狀態轉移方程:
d p[
i][j
]=if(p[j] ≠ '*') = \begin dp[i-1][j-1], & \text\\ false, &\text\\ \end\\ otherwise = \begin dp[i-1][j] or dp[i][j-2], & \text\\ dp[i][j-2], & \text \end \end
dp[i][
j]=⎩
⎪⎪⎪⎪
⎨⎪⎪⎪
⎪⎧i
f(p[
j]
=′∗′
)=}else}}
}return dp[m]
[n];
}public
boolean
ismatch
(string s, string p,
int i,
int j)
if( p.
charat
(j-1)==
'.')
return s.
charat
(i-1
)== p.
charat
(j-1);
}}
LeetCode第141題 環形鍊錶
給定乙個鍊錶,判斷鍊錶中是否有環。為了表示給定鍊錶中的環,我們使用整數 pos 來表示鍊錶尾連線到鍊錶中的位置 索引從 0 開始 如果 pos 是 1,則在該鍊錶中沒有環。示例 1 輸入 head 3,2,0,4 pos 1 輸出 true 解釋 鍊錶中有乙個環,其尾部連線到第二個節點。defini...
LeetCode第141題環形鍊錶
題目描述 給定乙個鍊錶,判斷鍊錶中是否有環。為了表示給定鍊錶中的環,我們使用整數 pos 來表示鍊錶尾連線到鍊錶中的位置 索引從 0 開始 如果 pos 是 1,則在該鍊錶中沒有環。解題思路 1 初步想法 沒有想法,估計是沒怎麼接觸鍊錶的題,看到別人的 用了兩個變數,乙個變數走一步,乙個變數走兩步,...
Leetcode第141題 環形鍊錶
給定乙個鍊錶,判斷鍊錶中是否有環。如果鍊錶中存在環,則返回 true 否則,返回 false 示例 1 輸入 head 3,2,0,4 pos 1 輸出 true 解釋 鍊錶中有乙個環,其尾部連線到第二個節點。示例 2 輸入 head 1,2 pos 0 輸出 true 解釋 鍊錶中有乙個環,其尾部...