擴充套件kmp:
擴充套件kmp可以用來解決很多字串問題,如求乙個字串的最長回文子串和最長重複子串。
【演算法】
設next[i]為滿足b[i…i+z-1]==b[0…z-1]的最大的z值(也就是b的自身匹配)。設目前next[0…lenb-1]與ex[0…i-1]均已求出,要用它們來求ex[i]的值。
設p為目前a串中匹配到的最遠位置,k為讓其匹配到最遠位置的值(或者說,k是在0<=i0k,所以又有a[i…p]==b[i-k…p-k],設l=next[i-k],則根據next的定義有b[0…l-1]==b[i-k…i-k+l-1]。考慮i-k+l-1與p-k的關係:
(1)i-k+l-1=l。又由於next的定義可得,
a[i+l]必然不等於b[l](否則a[i…i+l]==b[0…l],因為i+l<=p,所以a[i…i+l]==b[i-k…i-k+l],這樣b[0…l]==b[i-k…i-k+l],故next[i-k]的值應為l+1或更大),這樣,可以直接得到ex[i]=l!
(2)i+k-l+1>=p-k,即i+l>p。這時,首先可以知道a[i…p]和b[0…p-i]是相等的(因為a[i…p]==b[i-k…p-k],而i+k-l+1>=p-k,由b[0…l-1]==b[i-k…i-k+l-1]可得b[0…p-i]==b[i-k…p-k],即a[i…p]==b[0…p-i]),然
後,對於a[p+1]和b[p-i+1]是否相等,目前是不知道的(因為前面已經說過,p是目前a串中匹配到的最遠位置,在p之後無法知道任何一位的匹配資訊),因此,要從a[p+1]與b[p-i+1]開始往後繼續匹配(設j為目前
b的匹配位置的下標,一開始j=p-i+1,每次比較a[i+j]與b[j]是否相等,直到不相等或者越界為止,此時的j值就是ex[i]的值)。在這種情況下,p的值必然會得到延伸,因此更新k和p的值。
邊界:ex[0]的值需要預先求出,然後將初始的k設為0,p設為ex[0]-1。
對於求next陣列,也是「自身匹配」,類似kmp的方法處理即可。唯一的不同點也在邊界上:可以直接知道next[0]=lenb,next[1]的值預先求出,然後初始k=1,p=ex[1]。
需要嚴重注意的是,在上述的情況(2)中,本該從a[p+1]與b[p-i+1]開始匹配,但是,若p+1【時間複雜度分析】
在kmp和擴充套件kmp中,不管是a串還是b串,其匹配位置都是單調遞增的,故總時間複雜度是線性的,都為o(lena + lenb)(只是擴充套件kmp比kmp的常數更大一些)。
【應用】
kmp和擴充套件kmp在解決字串問題中有大用。很多看上去很猥瑣的字串問題,都可以歸結到這兩種演算法之中。另外,這裡的「字串」可以延伸為一切型別的陣列,而不僅僅是字元陣列。
**模板一
模板二#include
using
namespace std;
const
int n =
101010
;int next[n]
,extand[n]
;void
getnext
(char
*t)else next[k]
= l;}}
void
getextand
(char
*s,char
*t)else extand[k]
= l;}}
intmain()
}
應用const
int max=
100010
;//字串長度最大值
int next[max]
,extend[max]
;//預處理計算next陣列
void
getnext
(char str)
}}//計算extend陣列
void
exkmp
(char s1,
char s2)
}}
clairewd』s message hdu - 4300
題意:給你一張含有26個字母的密碼表,對應相應位置的字母a~z。再給你一組不完整的密文+明文,要求輸出完整的密文+明文。
思路:這道題問的就是將1個串如何變為stringa+stringb的形式,使得stringa是stringb經過對映得到相同的串。對映那步其實沒有什麼價值,假設str為原串s經過對映後得到的串,我們可以以str為模式串,以s為原串做一次擴充套件kmp,得到extend陣列,extend[i]表示原串以第i開始與模式串的字首的最長匹配。經過o(n)的列舉,我們可以得到,若extend[i]+i=len且i>=extend[i]時,表示stringb即為該點之前的串,stringa即為該點之前的str串,最後輸出即可。(將密文+明文翻譯過來,以原來的密文+明文為主串,翻譯後的字串為模式串,進行擴充套件kmp匹配。)
#include
#include
#include
#include
#include
using
namespace std;
int t,n,len;
char s[
100010
],t[
100010
],a[28]
;int next[
100010
],extand[
100010];
void
getnext
(char
*t)else next[k]
= l;}}
void
getextand
(char
*s,char
*t)else extand[k]
= l;}}
intmain()
}for
(int i=
0;i)printf
("%c"
,s[i]);
for(
int i=
0;i)printf
("%c"
,t[i]);
printf
("\n");
}}
擴充套件KMP演算法
擴充套件kmp 求出a i.lena 1 與b的最長公共字首長度,記為ex i 或者說,ex i 為滿足a i.i z 1 b 0.z 1 的最大的z值 擴充套件kmp可以用來解決很多字串問題,如求乙個字串的最長回文子串和最長重複子串。演算法 設next i 為滿足b i.i z 1 b 0.z 1...
擴充套件KMP演算法
摘自 問題定義 給定兩個字串s和t 長度分別為n和m 下標從0開始,定義extend i 等於s i s n 1 與t的最長相同字首的長度,求出所有的extend i 舉個例子,看下表 i0 1234 567s aaaa abbb taaa aacextend i 54 3210 00為什麼說這是k...
擴充套件kmp演算法
原文章 拓展kmp是對kmp演算法的擴充套件,它解決如下問題 定義母串s,和字串t,設s的長度為n,t的長度為m,求t與s的每乙個字尾的最長公共字首,也就是說,設extend陣列,extend i 表示t與s i,n 1 的最長公共字首,要求出所有extend i 0 i 從而得知extend 0 ...