摘自:
問題定義:給定兩個字串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為什麼說這是kmp演算法的擴充套件呢?顯然,如果在s的某個位置i有extend[i]
等於m,則可知在s中找到了匹配串t,並且匹配的首位置是i。而且,擴充套件kmp演算法可以找到s中所有t的匹配。接下來具體介紹下這個演算法。
如上圖,假設當前遍歷到s串位置i,即extend[0]...extend[i - 1]
這i個位置的值已經計算得到。設定兩個變數,a和p。p代表以a為起始位置的字元匹配成功的最右邊界,也就是"p = 最後乙個匹配成功位置 + 1"。相較於字串t得出,s[a...p)等於t[0...p-a)。
再定義乙個輔助陣列int next
,其中next[i]
含義為:t[i]...t[m - 1]
與t的最長相同字首長度,m為串t的長度。舉個例子:i0
s[i]
對應t[i - a]
,如果i + next[i - a] < p
,如上圖,三個橢圓長度相同,根據next陣列的定義,此時extend[i] = next[i - a]
。
如果i + next[i - a] == p
呢?如上圖,三個橢圓都是完全相同的,s[p] != t[p - a]
且t[p - i] != t[p - a]
,但s[p]
有可能等於t[p - i]
,所以我們可以直接從s[p]
與t[p - i]
開始往後匹配,加快了速度。
如果i + next[i - a] > p
呢?那說明s[i...p)
與t[i-a...p-a)
相同,注意到s[p] != t[p - a]
且t[p - i] == t[p - a]
,也就是說s[p] != t[p - i]
,所以就沒有繼續往下判斷的必要了,我們可以直接將extend[i]
賦值為p - i
。
(5)最後,就是求解next陣列。我們再來看下next[i]
與extend[i]
的定義:
恍然大悟,求解next[i]
的過程不就是t自己和自己的乙個匹配過程嘛,下面直接看**。
#include #include using namespace std;
/* 求解 t 中 next,注釋參考 getextend() */
void getnext(string & t, int & m, int next)
else
next[i] = next[i - a];
}}/* 求解 extend */
void getextend(string & s, int & n, string & t, int & m, int extend, int next)
else
extend[i] = next[i - a];
}}int main()
return 0;
}
資料測試如下:
aaaaabbb
aaaaac
next: 6 4 3 2 1 0
extend: 5 4 3 2 1 0 0 0
abcdef
next: 3 0 0
extend: 0 0 0
另,參考擴充套件kmp演算法文章:
擴充套件kmp演算法模板:
const int maxn=100010; //字串長度最大值
int next[maxn],ex[maxn]; //ex陣列即為extend陣列
//預處理計算next陣列
void getnext(char *str)
{ int i=0,j,po,len=strlen(str);
next[0]=len;//初始化next[0]
while(str[i]==str[i+1]&&i+1po+next[po],則要從頭開始匹配
while(i+jex[po]+po則要從頭開始匹配
while(i+j
擴充套件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演算法
擴充套件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為目前...
擴充套件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 ...