還是進入正題吧,整理整理大佬的blog
kmp演算法是一種改進的字串匹配演算法,由d.e.knuth,j.h.morris和v.r.pratt同時發現。kmp演算法的關鍵是利用匹配失敗後的資訊,儘量減少模式串與主串的匹配次數以達到快速匹配的目的。具體實現就是實現乙個next()函式,函式本身包含了模式串的區域性匹配資訊。時間複雜度o(m+n)。
我們首先用乙個圖來描述kmp演算法的思想。在字串s中尋找f,當匹配到位置i時兩個字串不相等,這時我們需要將字串t向前移動。常規方法是每次向前移動一位,但是它沒有考慮前i-1位已經比較過這個事實,所以效率不高。事實上,如果我們提前計算某些資訊,就有可能一次前移多位。假設我們根據已經獲得的資訊知道可以前移k位,我們分析移位前後的t有什麼特點。我們可以得到如下的結論:
所以前移k位之後,可以繼續比較位置i的前提是f的前i-1個位置滿足:長度為i-k-1的字首a和字尾b相同。只有這樣,我們才可以前移k位後從新的位置繼續比較。
所以kmp演算法的核心即是計算字串f每乙個位置之前的字串的字首和字尾公共部分的最大長度(不包括字串本身,否則最大長度始終是字串本身)。
獲得f每乙個位置的最大公共長度之後,就可以利用該最大公共長度快速和字串s比較。當每次比較到兩個字串的字元不同時,我們就可以根據最大公共長度將字串f向前移動(已匹配長度-最大公共長度)位,接著繼續比較下乙個位置。事實上,字串f的前移只是概念上的前移,只要我們在比較的時候從最大公共長度之後比較f和s即可達到字串f前移的目的。
理解了kmp演算法的基本原理,下一步就是要獲得字串f每乙個位置的最大公共長度。這個最大公共長度在演算法導論裡面被記為next陣列。在這裡要注意一點,next陣列表示的是長度,下標從1開始;但是在遍歷原字串時,下標還是從0開始。假設我們現在已經求得next[1]、next[2]、……next[i],分別表示長度為1到i的字串的字首和字尾最大公共長度,現在要求next[i+1]。由上圖我們可以看到,如果位置i和位置next[i]處的兩個字元相同(下標從零開始),則next[i+1]等於next[i]加1。如果兩個位置的字元不相同,我們可以將長度為next[i]的字串繼續分割,獲得其最大公共長度next[next[i]],然後再和位置i的字元比較。這是因為長度為next[i]字首和字尾都可以分割成上部的構造,如果位置next[next[i]]和位置i的字元相同,則next[i+1]就等於next[next[i]]加1。如果不相等,就可以繼續分割長度為next[next[i]]的字串,直到字串長度為0為止。由此我們可以寫出求next陣列的**:
void cal_next(char *str, int *next, int計算完成next陣列之後,我們就可以利用next陣列在字串s中尋找字串f的出現位置。匹配的**和求next陣列的**非常相似,因為匹配的過程和求next陣列的過程其實是一樣的。假設現在字串f的前i個位置都和從某個位置開始的字串s匹配,現在比較第i+1個位置。如果第i+1個位置相同,接著比較第i+2個位置;如果第i+1個位置不同,則出現不匹配,我們依舊要將長度為i的字串分割,獲得其最大公共長度next[i],然後從next[i]繼續比較兩個字串。這個過程和求next陣列一致,所以可以匹配**如下:len)
if (str[k + 1] == str[q])//
如果相同,k++
next[q] = k;//
這個是把算的k的值(就是相同的最大字首和最大字尾長)賦給next[q]
}}
int kmp(char *str, int slen, char *ptr, intplen)
}return -1
; }
KMP演算法深入淺出
s ababcababa p ababa kmp演算法與bf演算法的區別就在於kmp演算法巧妙的消除了指標i的回溯問題,只需確定下次匹配j的位置即可,使得問題的複雜度由o mn 下降到o m n 在kmp演算法中,為了確定在匹配不成功時,下次匹配時j的位置,引入了next陣列,next j 的值表示...
深入淺出K Means演算法
摘要 在資料探勘中,k means演算法是一種 cluster analysis 的演算法,其主要是來計算資料聚集的演算法,主要通過不斷地取離種子點最近均值的演算法。在資料探勘中,k means演算法是一種cluster analysis的演算法,其主要是來計算資料聚集的演算法,主要通過不斷地取離種...
深入淺出K Means演算法
在資料探勘中,k means演算法是一種 cluster analysis 的演算法,其主要是來計算資料聚集的演算法,主要通過不斷地取離種子點最近均值的演算法。在資料探勘中,k means演算法是一種cluster analysis的演算法,其主要是來計算資料聚集的演算法,主要通過不斷地取離種子點最...