kmp 演算法導讀

2021-06-25 12:36:31 字數 3055 閱讀 1655

【kmp演算法簡介】

kmp演算法是一種改進後的字串匹配演算法,由d.e.knuth與v.r.pratt和j.h.morris同時發現,因此人們稱它為克努特——莫里斯——普拉特操作(簡稱kmp演算法)。通過乙個輔助函式實現跳過掃瞄不必要的目標串字元,以達到優化效果。

【傳統字串匹配演算法的缺憾】

bill認為,對於一種優化的演算法,既要知道優化的細節,也更應該了解它的前身(至於kmp是否基於傳統演算法,我不清楚,這裡只作語境上的前身),了解是什麼原因導致了人們要去優化它,因此加入了這一段:

請看以下傳統字串匹配的**:

c++ code

void nativestrmatching( elemtype target, elemtype pattern )            

}            

不妨設模式串pattern = "a  b  c  c  a  b  c  c  a  b  c  a"

pattern 陣列編號: 0  1  2  3  4  5  6  7  8  9 10 11

nocm 表示 已經匹配的字元數

lolp 表示 既是自身真字尾又是自身最長字首的字串長度

以下是計算流程:

prefixfunc[1] = 0; //只匹配乙個字元就失配時,顯然該值為零

lolp = 0;   nocm = 2;   lolp = 0;    prefixfunc[2] = 0;

lolp = 0;   nocm = 3;   lolp = 0;    prefixfunc[3] = 0;

lolp = 0;   nocm = 4;   lolp = 0;    prefixfunc[4] = 0;

lolp = 0;   nocm = 5;   lolp = 1;    prefixfunc[5] = 1;

lolp = 1;   nocm = 6;   lolp = 2;    prefixfunc[6] = 2;

lolp = 2;   nocm = 7;   lolp = 3;    prefixfunc[7] = 3;

lolp = 3;   nocm = 8;   lolp = 4;    prefixfunc[8] = 4;

lolp = 4;   nocm = 9;   lolp = 5;    prefixfunc[9] = 5;

lolp = 5;   nocm = 10; lolp = 6;    prefixfunc[10] = 6;

lolp = 6;   nocm = 11; lolp = 7;    prefixfunc[11] = 7;

lolp = 7;   nocm = 12;

---------此時滿足條件while( lolp>0 && (pattern[lolp] != pattern[nocm-1]) )-------------

while語句中的執行

lolp = 0;   nocm = 12; lolp = 1;    prefixfunc[12] = 1;

最後我們的字首函式 prefixfunc =

其間最精妙的要屬失配時的操作

while( lolp>0 && (pattern[lolp] != pattern[nocm-1]) )

lolp = prefixfunc[lolp];

其中 lolp = prefixfunc[lolp];  遞迴呼叫prefixfunc函式,直到整個p字串都再無最長字首或者找到乙個之前的滿足條件的最長字首。

【應用字首函式優化傳統匹配演算法——kmp演算法實現】

由以上分析,不難推導kmp演算法的實現

c++ code

void kmpstrmatching( elemtype target, elemtype pattern )            

{            

int prefixfunc[max_size];            

register int tarlen = 0;            

register int patlen = 0;            

// compute the length of array target and pattern            

while( '\0' != target[tarlen] )            

tarlen++;            

while( '\0' != pattern[patlen] )            

patlen++;            

// compute the prefix function of pattern            

cptpffunc( pattern, prefixfunc );            

int nocm = 0;     // number of characters matched            

for( int i=0; i0 && pattern[nocm] != target[i] )            

nocm = prefixfunc[nocm];            

if( pattern[nocm] == target[i] )            

nocm++;            

if( nocm == patlen )            

{            

cout<<"kmp string matching,pattern occurs with shift "<

/*** 由於時間關係,沒能將上述kmp演算法的實現細節一一講清,以後有時間補上

*/【參考文獻】

《introduction to algorithms》second edition

by thomas h. cormen, charles e. leiserson, ronald l. rivest and clifford .

本文出自 「bill_hoo專欄」 部落格,請務必保留此出處

演算法 KMP演算法

kmp演算法主要解決的問題就是在字串 主串 中的模式 pattern 定位問題。記主串為t,模式串為p,則kmp演算法就是返回p在t 現的具體位置,如果沒有出現則返回 1。如果 i 指標指向的字元和 j 指標指向的字元不一致,那麼把 i 右移1位,j 從0位開始,從新開始匹配 如果 i 指標指向的字...

kmp演算法next例題 KMP演算法next陣列求解

kmp演算法與bf演算法的比較 bf演算法的想法十分樸素,即先將子串t的第一位與主串s的第一位對齊開始匹配,當不能匹配時將子串整體往後移一位,然後重新匹配,以此類推直至排出結果 如當遇到下圖所示情況時,需將子串整體後移一位,將i,j分別回溯到主串第2位和子串第一位。kmp演算法 對bf進行思考後,我...

KMP及KMP改進演算法

kmp 看毛片 演算法確實很難理解,上網搜了半天想了很久才大概想明白。kmp演算法精華在於next陣列 部分匹配值 即next陣列就是 字首 和 字尾 的最長的共有元素的長度。以 abcdabd 為例,a 的字首和字尾都為空集,共有元素的長度為0 ab 的字首為 a 字尾為 b 共有元素的長度為0 ...