劍指Offer五十二 正規表示式匹配

2021-10-04 22:43:07 字數 3474 閱讀 4303

請實現乙個函式用來匹配包括』.『和』『的正規表示式。模式中的字元』.『表示任意乙個字元,而』'表示它前面的字元可以出現任意次(包含0次)。 在本題中,匹配是指字串的所有字元匹配整個模式。例如,字串"aaa"與模式"a.a"和"abaca"匹配,但是與"aa.a"和"ab*a"均不匹配

首先狀態 dp 一定能自己想出來。

dp[i][j]表示s的前i個是否能被p的前j個匹配

怎麼想轉移方程?首先想的時候從已經求出了dp[i-1][j-1]入手,再加上已知s[i]、p[j],要想的問題就是怎麼去求dp[i][j]

已知dp[i-1][j-1] 意思就是前面子串都匹配上了,不知道新的一位的情況。

那就分情況考慮,所以對於新的一位 p[j] s[i] 的值不同,要分情況討論:

考慮最簡單的p[j] == s[i] : dp[i][j] = dp[i-1][j-1]

然後從 p[j] 可能的情況來考慮,讓 p[j]=各種能等於的東西。

p[j] == "." : dp[i][j] = dp[i-1][j-1]

p[j] ==" * ":

第乙個難想出來的點:怎麼區分 * 的兩種討論情況

首先給了*,明白*的 含義是 匹配零個或多個前面的那乙個元素,所以要考慮他前面的元素p[j-1]*跟著他前乙個字元走,前乙個能匹配上s[i]*才能有用,前乙個都不能匹配上s[i]*也無能為力,只能讓前乙個字元消失,也就是匹配0次前乙個字元。

所以按照 p[j-1] 和 s[i] 是否相等,我們分為兩種情況:

3.1p[j-1] != s[i] : dp[i][j] = dp[i][j-2]

這就是剛才說的那種前乙個字元匹配不上的情況。

比如(ab, abc * )。遇到*往前看兩個,發現前面 s[i] 的 ab 對 p[j-2] 的 ab 能匹配,雖然後面是 c*,但是可以看做匹配 0 次 c,相當於直接去掉 c ,所以也是 true。注意 (ab, abc*) 是 false。

3.2p[j-1] == s[i] or p[j-1] == ".":

*前面那個字元,能匹配s[i],或者 * 前面那個字元是萬能的 .

因為. *就相當於. .,那就只要看前面可不可以匹配就行。

比如 (##b , ###b *),或者( ##b , ### . * )只看###後面一定是能夠匹配上的。

所以要看bb *前面那部分## 的地方匹不匹配。

第二個難想出來的點:怎麼判斷前面是否匹配

dp[i][j] = dp[i-1][j] // 多個字元匹配的情況

or dp[i][j] = dp[i][j-1] // 單個字元匹配的情況

or dp[i][j] = dp[i][j-2] // 沒有匹配的情況

看 ### 匹不匹配,不是直接只看 ### 匹不匹配,要綜合後面的 b b* 來分析

這三種情況是 or的關係,滿足任意一種都可以匹配上,同時是最難以理解的地方:

dp[i-1][j]就是看 s 裡 b 多不多, ### 和 ###b * 是否匹配,一旦匹配,s 後面再添個 b 也不影響,因為有 * 在,也就是 ###b 和 ###b *也會匹配。

dp[i][j-1] 就是去掉 * 的那部分,###b 和 ###b 是否匹配,比如 qqb qqb

dp[i][j-2]就是 去掉多餘的 b ,p 本身之前的能否匹配,###b 和 ### 是否匹配,比如 qqb qqbb 之前的 qqb qqb 就可以匹配,那多了的 b * 也無所謂,因為 b * 可以是匹配 00 次 b,相當於 b * 可以直接去掉了。

三種滿足一種就能匹配上。

為什麼沒有 dp[i-1][j-2] 的情況? 就是 ### 和 ### 是否匹配?因為這種情況已經是 dp[i][j-1] 的子問題。也就是 s[i]==p[j-1],則 dp[i-1][j-2]=dp[i][j-1]。

最後來個歸納:

如果 p.charat(j) == s.charat(i) : dp[i][j] = dp[i-1][j-1];

如果 p.charat(j) == 『.』 : dp[i][j] = dp[i-1][j-1];

如果 p.charat(j) == '』:

1. 如果 p.charat(j-1) != s.charat(i) : dp[i][j] = dp[i][j-2] //in this case, a only counts as empty

2. 如果 p.charat(i-1) == s.charat(i) or p.charat(i-1) == 『.』:

dp[i][j] = dp[i-1][j] //in this case, a* counts as multiple a

or dp[i][j] = dp[i][j-1] // in this case, a* counts as single a

or dp[i][j] = dp[i][j-2] // in this case, a* counts as empty

public

boolean

ismatch

(string s,string p)

boolean

dp =

newboolean

[s.length()

+1][p.

length()

+1];

dp[0]

[0]=

true

;//dp[i][j] 表示 s 的前 i 個是否能被 p 的前 j 個匹配

for(

int i =

0; i < p.

length()

; i++)}

for(

int i =

0; i < s.

length()

; i++)if

(p.charat

(j)==

'*')

else}}

}return dp[s.

length()

][p.

length()

];}

劍指offer 正規表示式匹配

請實現乙個函式用來匹配包括 和 的正規表示式。模式中的字元 表示任意乙個字元,而 表示它前面的字元可以出現任意次 包含0次 在本題中,匹配是指字串的所有字元匹配整個模式。例如,字串 aaa 與模式 a.a 和 abaca 匹配,但是與 aa.a 和 aba 均不匹配 由於只涉及兩種正規表示式的匹配,...

劍指Offer 正規表示式匹配

題目 請實現乙個函式用來匹配包括 和 的正規表示式。模式中的字元 表示任意乙個字元,而 表示它前面的字元可以出現任意次 包含0次 在本題中,匹配是指字串的所有字元匹配整個模式。例如,字串 aaa 與模式 a.a 和 ab ac a 匹配,但是與 aa.a 和 ab a 均不匹配 實現 class s...

劍指offer 正規表示式匹配

題目 請實現乙個函式用來匹配包括 和 的正規表示式。模式中的字元 表示任意乙個字元,而 表示它前面的字元可以出現任意次 包含0次 在本題中,匹配是指字串的所有字元匹配整個模式。例如,字串 aaa 與模式 a.a 和 ab ac a 匹配,但是與 aa.a 和 ab a 均不匹配.分析 觀察模式串中第...