kmp
演算法詳解
——適合初學
kmp演算法的朋友
【kmp
演算法詳解
——適合初學
kmp演算法的朋友】
2010-10-27 16:22:33
原始出處
、作者資訊和本宣告。
相信很多人(包括自己)初識
kmp演算法的時候始終是丈二和尚摸不著頭腦,要麼完全不知所云,要麼看不懂書上的解釋,要麼自己覺得好像心裡了解
kmp演算法的意思,卻說不出個究竟,所謂知其然不知其所以然是也。
經過七八個小時地仔細研究,終於感覺自己能說出其所以然了,又覺得資料結構書上寫得過於簡潔,不易於初學者接受,於是決定把自己的理解拿出來與大家分享,希望能拋磚引玉,這便是
bill
寫這篇文章想要得到的最好結果了
-----------------------------------
謹以此文,獻給剛接觸
kmp演算法的朋友,定有不足之處,望大家指正
----------------------------------------
【
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 .
KMP演算法詳解 適合初學KMP演算法的朋友
相信很多人 包括自己 初識kmp演算法的時候始終是丈二和尚摸不著頭腦,要麼完全不知所云,要麼看不懂書上的解釋,要麼自己覺得好像心裡了解kmp演算法的意思,卻說不出個究竟,所謂知其然不知其所以然是也。經過七八個小時地仔細研究,終於感覺自己能說出其所以然了,又覺得資料結構書上寫得過於簡潔,不易於初學者接...
KMP演算法詳解 適合初學KMP演算法的朋友
相信很多人 包括自己 初識kmp演算法的時候始終是丈二和尚摸不著頭腦,要麼完全不知所云,要麼看不懂書上的解釋,要麼自己覺得好像心裡了解kmp演算法的意思,卻說不出個究竟,所謂知其然不知其所以然是也。經過七八個小時地仔細研究,終於感覺自己能說出其所以然了,又覺得資料結構書上寫得過於簡潔,不易於初學者接...
KMP演算法初學
kmp演算法是一種改進的模式匹配演算法,與樸素的模式演算法 即模式串與主串逐一匹配,匹配失敗模式串整體右移一位再次逐一匹配至完全匹配成功 相比,主串中指標無需回溯,時間複雜度為o n m n為主串長,m為模式串長 樸素為o n m 一 next陣列kmp演算法中多了乙個next陣列,要用kmp演算法...