KMP演算法模板及各種應用

2021-08-26 18:29:47 字數 2908 閱讀 1151

給定乙個字串,問最多是多少個相同子串不重疊連線構成。

kmp的next陣列應用。這裡主要是如何判斷是否有這樣的子串,和子串的個數。

若為abababa,顯然除其本身外,沒有子串滿足條件。而分析其next陣列,next[7] = 5,next[5] = 3,next[3] = 1,即str[2..7]可由ba子串連線構成,那怎麼否定這樣的情況呢?很簡單,若該子串滿足條件,則len%sublen必為0。sunlen可由上面的分析得到為len-next[len]。

因為子串是首尾相接,len/sublen即為substr的個數。

若l%(l-next[l])==0,n = l/(l-next[l]),else n = 1

#include#includeusing namespace std;

char pattern[1000002];

int next[1000002];

/*kmp演算法,需要首先求出模式串的next函式值

next[j] = k,說明 p0pk-1 == pj-kpj-1,也就是說k為其前面相等串的長度

*/void get_nextval(const char* pattern)

else

j=next[j]; //若j值不相同,則j值回溯

}}//get_nextval

int main(void)

return 0;

}

大意:定義字串a,若a最多由n個相同字串s連線而成,則a=s^n,如"aaa" = "a"^3,"abab" = "ab"^2

"ababa" = "ababa"^1

給出乙個字串a,求該字串的所有字首中有多少個字首sa= s^n(n>1)

輸出符合條件的字首長度及其對應的n

如aaa

字首aa的長度為2,由2個'a'組成

字首aaa的長度為3,由3個"a"組成

分析:kmp

若某一長度l的字首符合上訴條件,則

1.next[l]!=0(next[l]=0時字串為原串,不符合條件)

2.l%(l-next[l])==0(此時字串的長度為l/next[l])

對於2:有str[0]....str[next[l]-1]=str[l-next[l]-1]...str[l-1]

=》str[l-next[l]-1] = str[l-next[l]-1+l-next[l]-1] = str[2*(l-next[l]-1)];

假設s = l-next[l]-1;則有str[0]=str[s]=str[2*s]=str[3*s]...str[k*s],對於所有i%s==0,均有s[i]=s[0]

同理,str[1]=str[s+1]=str[2*s+1]....

str[j]=str[s+j]=str[2*s+j]....

綜上,若l%s==0,則可得l為str[0]...str[s-1]的相同字串組成,

總長度為l,其中字串長度sl = s-0+1=l-next[l],迴圈次數為l/sl

故對於所有大於1的字首,只要其符合上述條件,即為答案之一

#include#include#includeusing namespace std;

char pattern[1000002];

int next[1000002];

/*kmp演算法,需要首先求出模式串的next函式值

next[j] = k,說明 p0pk-1 == pj-kpj-1,也就是說k為其前面相等串的長度

*/void get_nextval(const char* pattern)

else

j=next[j];

}}//get_nextval

int main(void)

printf("\n");

}return 0;

}

大意:給出乙個字串a,求a有多少個字首同時也是字尾,從小到大輸出這些字首的長度。

分析:kmp

對於長度為len的字串,由next的定義知:

a[0]a[1]...a[next[len]-1]=a[len-next[len]]...a[len-1]此時a[0]a[1]...a[next[len]-1]為乙個符合條件的字首

有a[0]a[1]....a[next[next[len]]-1] = a[len-next[next[len] - next[next[len]]]...a[next[len]-1],故a[0]a[1]....a[next[next[len]]-1]也是乙個符合條件的字首

故從len=>next[len]=>next[next[len]] ....=>直到某個next為0均為合法答案,注意當首位單詞相同時,也為答案。

#include#include#include#includeusing namespace std;

char pattern[400002];

int next[400002];

/*kmp演算法,需要首先求出模式串的next函式值

next[j] = k,說明 p0pk-1 == pj-kpj-1,也就是說k為其前面相等串的長度

*/void get_nextval(const char* pattern)

else

j=next[j];

}}//get_nextval

int main(void)

if(pattern[0]==pattern[n-1]) //首部、尾部字元相同

ans.push_back(1);

i=ans.size()-1;

for(;i>0;i--)

printf("%d ",ans[i]);

printf("%d\n",ans[0]);

} return 0;

}

KMP演算法詳解及各種應用

kmp演算法詳解 kmp演算法之所以叫做kmp演算法是因為這個演算法是由三個人共同提出來的,就取三個人名字的首字母作為該演算法的名字。其實kmp演算法與bf演算法的區別就在於kmp演算法巧妙的消除了指標i的回溯問題,只需確定下次匹配j的位置即可,使得問題的複雜度由o mn 下降到o m n 在kmp...

KMP演算法及應用

kmp演算法用來解決一系列字串單模式匹配問題,其以難理解,難記憶著稱。其next陣列的構造就如同ac自動機中的fail指標,就是如果匹配失敗,字串應從 開始繼續匹配。這裡的next陣列表示 next i 前i個字元的公共最長前字尾長度。覺得對於kmp演算法,這篇寫的不錯 現在來講一下應用。給定兩個字...

KMP詳細解釋及KMP演算法模板

kmp是什麼,kmp解決什麼型別的問題 kmp全稱為knuth morris pratt演算法,是一種高效的字串匹配演算法,尋找乙個字串中是否包含另乙個字串,例如 char s ababababcab char p ababc s為模板串 主串 p為子串,在s中找到p的位置 暴力匹配演算法 o n ...