動態規劃之正規表示式匹配

2021-10-09 11:54:01 字數 2155 閱讀 6418

正規表示式匹配是真真的經典筆試、面試題了,這傢伙的動態規劃狀態轉移的細節得扣的仔仔細細,不然就是漏洞百出,著實細節魔鬼。當然本身的動態思路也是屬於比較困難的。很早之前做過的這題,再次覆盤發現還是會出問題。還是需要整理整理思路。

力扣10.正規表示式匹配

關於題幹就不在詳述了,可以直接參考力扣原題。感謝力扣。

所謂字串匹配,本質上就是驗證兩個串是否相同,初步的,相信判斷兩個字串是否相同,大家都知道怎麼處理。正規表示式則是在基礎上,新增了一些具有特殊功能的字元。在本題中,設模板串為s,待測串為p。

'.'可以替代任何字母

'*'可以重複其前乙個字母0~任意次數

根據子串行、子串一類的經驗,可以想到,動態規劃的狀態必然有兩種,即模板串的長度和待檢查串的長度。子問題即更短的串的匹配。

狀態有兩個,顯然是二維dp,定義dp陣列含義如下:

dp[i]

[j]表示s中前i個字元與p中前j個字元的匹配情況

選擇,即在模板串長度一定時,考慮p串第j個字元的匹配情況。分為三類

p[j]為字母

p[j]

==『.』

p[j]

=='*'

其中,根據題意,'.'可以匹配任何字元,即可讓其等於s[i]。因此,合併前兩種情況如下:

若s[i]

==p[j] 或 p[j]

=='.'時

dp[i]

[j]=dp[i-1]

[j-1];

//兩者均向前移動乙個狀態進行轉移

否則,無法匹配

第三種情況略顯複雜,出現'*'時,我們需要考慮到底讓之前的那個字元重複幾次?從直觀的想法來看,我們可以列舉所有可能重複的次數,來判斷當前的匹配是否成功。下面來舉例子。

當重複0次

前乙個字元在匹配中不出現

即p[j]和p[j-

1]是否出現沒有區別,把它倆扔開不管

dp[i]

[j]=dp[i]

[j-2];

//因此從j-2

當重複1次

前乙個字元在匹配**現1次

即p[j-

1]存在

if(s[i]

==p[j-1]

) dp[i]

[j]=dp[i-1]

[j-2

]

當重複3次

前乙個字元在匹配**現2次

即p[j-

1]存在2次

if(s[i]

==p[j-1]

==s[i-1]

) dp[i]

[j]=dp[i-2]

[j-2

]

即重複幾次,需要在s中向前匹配幾個相同的字元。這就是所謂的列舉。但是這樣一來會大大增加時間複雜度,並不理想。

實際上,列舉的過程就是向前看s中是否存在當前字元的重複段,實際上,在之前的狀態轉移中,這些檢查已經完成了。因此,本質上只需要考慮當前字元出現與否。

若出現了,假設s[i]==s[i-1],dp[i][j]相當於在dp[i-1][j]上進行了轉移,將p[j]多重複出現了一次。再者,如果沒有出現,就是0次重複的狀態。因此,此時的轉移方程為

dp[i]

[j]=dp[i-1]

[j] | dp[i]

[j-2

];

綜上,整體的狀態轉移如下,注意字串的索引越界問題。

if

(p[j-1]

=='*'

)else

考慮base case就是,兩個空串匹配成功。

貼上完整**

class

solution

public

:bool

ismatch

(string s, string p)

else}}

return dp[m]

[n];}}

;

正規表示式匹配 動態規劃專題

二 題目解析 3.遞迴 給定乙個字串 s 和乙個字元模式 p 實現支援.和 的正規表示式匹配。匹配應該覆蓋整個字串 s 而不是部分字串。輸入 s aa p a 輸出 false 解釋 a 無法匹配 aa 整個字串。輸入 s aa p a 輸出 true 解釋 代表可匹配零個或多個前面的元素,即可以匹...

LeetCode 正規表示式匹配(動態規劃)

難度 困難 給你乙個字串s和乙個字元規律p,請你來實現乙個支援 和 的正規表示式匹配。所謂匹配,是要涵蓋整個字串s的,而不是部分字串。示例1 輸入 s aa p a 輸出 false 解釋 a 無法匹配 aa 整個字串。示例2 輸入 s aab p c a b 輸出 true 解釋 因為 表示零個或...

正規表示式 匹配

字串 void abtr quint32 ab 表示乙個正規表示式 template class bidirectionaliterator class allocator std allocator sub match bidirectionaliterator class match resul...