以下摘自
求出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]的最大的z值(也就是b的自身匹配)。設目前next[0..lenb-1]與ex[0..i-1]均已求出,要用它們來求ex[i]的值。
設p為目前a串中匹配到的最遠位置,k為讓其匹配到最遠位置的值(或者說,k是在0 <= i0 < i的所有i0值中,使i0+ex[i0]-1的值最大的乙個,p為這個最大值,即k+ex[k]-1),
顯然,p之後的所有位都是未知的,也就是目前還無法知道a[p+1..lena-1]中的任何一位和b的任何一位是否相等。
根據ex的定義可得,a[k..p]==b[0..p-k],因為i>k,所以又有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 < p-k,即i+l<=p。這時,由a[i..p]==b[i-k..p-k]可以得到a[i..i+l-1]==b[i-k..i-k+l-1],又因為b[0..l-1]==b[i-k..i-k+l-1]所以a[i..i+l-1]==b[0..l-1],這就說明ex[i]>=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< i,也就是p-i+1<0(這種情況是有可能發生的,當ex[i-1]=0,且前面的ex值都沒有延伸到i及以後的時候)的話,需要將a、b的下標都加1(因為此時p必然等於i-2,如果a、b的下標用兩個變數x、y控制的話,x和y都要加1)!!
【時間複雜度分析】
在kmp和擴充套件kmp中,不管是a串還是b串,其匹配位置都是單調遞增的,故總時間複雜度是線性的,都為o(lena + lenb)(只是擴充套件kmp比kmp的常數更大一些)。
【應用】
kmp和擴充套件kmp在解決字串問題中有大用。很多看上去很猥瑣的字串問題,都可以歸結到這兩種演算法之中。另外,這裡的「字串」可以延伸為一切型別的陣列,而不僅僅是字元陣列。
#include
#include
#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;
}}int main() }/*
aaaabaaa aaaa
*/
擴充套件KMP詳解
最近新學的三個演算法,一直都沒寫部落格,字尾自動機和線性基還有一點小尾巴,爭取這兩天結束 求 t 串與 s 串的每個字尾的最長公共字首 假設當前遍歷到s串位置i,即nxts 0 nxts i 1 這i個位置的值已經計算得到。設定兩個變數,st和pos。pos代表以st為起始位置的字元匹配成功的最右邊...
KMP 擴充套件KMP
本文將不斷加入例題,稍安勿躁,今天的總結爭取9 30寫完.kmp,中文名字叫字串匹配,用於解決一類字串匹配問題.先下一些定義 首先我們先想一想 nxt i 對於求解問題有怎樣的幫助.我們對於每乙個 t i s 1 的位置都匹配一次,這樣子複雜度為 theta n m 的.考慮在暴力匹配中其實我們不一...
擴充套件kmp
出自 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...