KMP演算法模板與解析

2021-09-27 19:21:22 字數 2681 閱讀 1050

全部資料結構、演算法及應用課內模板:

將kmp演算法,就要先講講它是用來幹什麼的,為什麼叫這個名字,暴力的演算法又是怎樣的

kmp是三人knuth,morris,pratt,他們仨發明了這個演算法,所以叫kmp。。。(不要驚訝。。)

然後它是用來解決字串的模式匹配問題(大白話就是找子串)

舉個例子說就是,給你乙個主串 s ,模式串 t,問你s裡含有多少個子串t,子串開頭下標多少

比如 s=aaaaa t=aa,於是有4個子串,下標分別是0,1,2,3

再比如

有1個子串,下標5

然後說一說暴力的演算法,也就是你沒學過kmp保證就那樣去寫了

叫做bf演算法,暴風(brute force)演算法(就是暴力啦~),是普通的模式匹配演算法

或者也可以叫做 *****strmatching 樸素的模式匹配演算法

暴力的方法事實上就是很單純的二重迴圈,s下標0開始,然後每次t下標0開始去和s比較

時間複雜度o(nm)

然後人們意識到,t每次向後挪一位很沒必要,然後從下標0開始一位一位地比較也完全沒必要

比如還是上面那個st

第一輪比較結果:

*****的暴力演算法接下來會比較:

並且挪到2號位的時候,t也會從0開始比較

這時候k、m、p三個人就開始研究人眼的匹配特性了

第一輪比較中,t匹配上的字首串是 : abab

這一串有 真字首串:a、ab、aba

真字尾串:b、ab、bab

他們發現,上述加粗的部分相同

於是規律性的東西出現了,我們再來看一下第一輪比較的圖

對於t t01=t23,然後看字尾23,s23=t23=t01

於是將 t01挪至s23,並直接比較s4和t2即可

所以,kmp演算法原理總結成一句話為:

比較失敗時,看已匹配成功的字首串a,取a的乙個真字尾串y,有乙個a的真字首串x與之相等

且此時lenx(=leny)長度盡可能長,將x挪至y的位置,直接比較x的下乙個字元和失敗位置的字元

不斷迴圈以上操作,直到無法繼續匹配

事實上,這個演算法還遠遠沒有說完

每次都現找字尾和與之對應的字首,時間又是很複雜

於是要先預處理出來對應位置儲存起來

比方說 abab 的 3號b 對應長度為 2(ab)

我們把這個稱之為特徵數n

對ababa有

於是這時我們再來看第一輪匹配

i=j=4時,匹配失敗,於是移動後 j=n[ j-1 ],接著比較 s[ i ] 與 t[ j ] 即可

當然,如果 j=0(第一位)就已經不相等了就沒有n[-1]了,就直接向後移動一位 i 就好

然後預處理特徵數n的時候如果太過暴力又會很慢

用動態規劃的思想去考慮,預處理這個東西的本質也是乙個kmp

比方說4號位的a,n[ 3 ]=2,於是直接 主:t[ 4 ] 和 模式:t[ 2 ]比較

發現 t[4]==t[2],於是 n[4]=n[3]+1=3,接著判斷第5位(當然上面這個串沒有5,那就結束了)

假設 t[ 4 ] != t[ 2 ],那麼就接著判斷當前真字首串的真字首串的下一位,就是去找判斷n[ n[ 3 ] - 1 ]即n[ 1 ]

然後不斷重複這樣的操作直到相等

當然,假設判斷到 0 還不相等,那麼 n[ 4 ]就=0

kmp演算法模板如下:(複雜度o(n+m))

char s[maxn],t[maxm]; //主串s,模式串t 

int n,m,n[maxm],cnt; //主串長n,模式串長m,特徵數n,成功匹配個數cnt

vectorpos; //成功匹配位置所有下標(第乙個字元)

void get_next(){

m=strlen(t);

for(int i=1;ikmp演算法模板題:

可以交一發檢驗下自己寫的kmp對不對

KMP演算法總結與模板

發現學了好久了kmp了,模板卻總是背不會,感覺自己還是沒有理解深刻,僅以此作為複習 給定乙個模式串s長度為m,和模板串p長度為n,求解模板串p在模式串s 現的位置 模板串p需要同模式串s匹配很多次,當乙個字元匹配失效時,傳統的演算法往往模板串p會整個從頭開始,導致演算法的時間複雜度是o m n o ...

KMP演算法(模板)

time limit 1000ms memory limit 65536k 有疑問?點這裡 給定兩個字串string1和string2,判斷string2是否為string1的子串。輸入包含多組資料,每組測試資料報含兩行,第一行代表string1 長度小於1000000 第二行代表string2 長...

KMP演算法模板

在文字t 1.n 中找到某個模式p 1.m 所有出現的位置被稱作字串匹配問題 m n p3375 模板 kmp字串匹配 這道題在洛谷上的評級居然是普及 普及?qvq 實現起來還是比較簡單的,只不過有很多細節可以有很多種寫法,看別人的 容易凌亂。理解起來比較困難的部分是如何get next 不建議初學...