這種演算法是d.e.knuth與v.r.pratt和j.h.morris同時發現的,因此人們稱它為克努特—莫里斯—普拉特演算法(簡稱為kmp演算法)。此演算法可以在o(m+n)的時間數量級上完成串的模式匹配操作。
其改進在於:每當一趟匹配過程中出現字元比較不等時,不需要回溯 i 指標,而是利用已經得到的「部分匹配」的結果將模式向右「滑動」盡可能遠的距離後,繼續進行比較。
模式串的next函式定義:
由此定義可推出下列模式串的next函式值:
計算next總原則(非常重要):
計算next[j]函式值,必從j-1位置開始(不是j),以j-1為節點號,next[j-1]為鍊錶尾指標,一直往前查詢,直到找到與arr[j-1]值相同的位置時(k)停止,則此時next[j]=next[k]+1。(注:將上述**抽象為鍊錶,從後往前的鍊錶)
幾大注意事項:
a)next[0]一般不使用,直接將next[1]=0,next[2]=1,j從1開始,j和next[j]有一一對應關係;
(注:如果非要使用next[0]的話,則置next[1]=-1,next[2]=0)
b)乙個特殊狀態,如果按照上述總原則,無法找到與arr[j-1]值相同的位置。則一律置next[j]=1。
為了形式化,首先,將上述**轉化為雙親表示法樹狀結構如下:
示例next[5],求法;
示例next[3],求法;
以下留下幾個**,供手動模擬練習一下計算過程:
前面定義的next函式在某些情況下尚有缺陷(進行了某些不必要的匹配,如下圖)。為了解決該問題引入了nextval對next進行修正。
接下來繼續使用上述,問題為材料對next進行修正:
在計算出next之後,得出nextval十分之簡單,用以下**表示更直接:
if (arr[j]==arr[next[j]])
就是判斷arr[j]與其next[j]所對應的arr[next[j]]是否相同,相同則修正,否則不需要修正。
附next/nextval測試:
#include int next[9];
//不修正
int getnextj(char arr, int j)
//④不等於,繼續找下去
k = next[k];
} //⑤未找到,恆置1
return 1; }
//修正
void getnextval(char arr) }
}int main(void)
//列印
printf("----next---\n");
for ( j = 1; j <= 8 ;++j)
//修正
getnextval(arr);
printf("\n----nextval---\n");
for ( j = 1; j <= 8 ;++j)
printf("\n");
return 0;
}
----next---
0 1 1 2 2 3 1 2
----nextval---
0 1 0 2 1 3 0 2
press any key to continue
KMP演算法初探
edit by xingoo kmp演算法其實就是一種改進的字串匹配演算法。複雜度可以達到o n m n是參考字串長度,m是匹配字串長度。傳統的演算法,就是匹配字串與參考字串挨個比較,如果相同就比較下乙個,如果不相同,就返回上一次的結果,再重新比較。如圖1 如果失敗則字串會重新用s 參考字串 的第二...
KMP演算法初探
求出乙個字串的next陣列 字串 next陣列 static int getnextarray string t else next j 0 當k 1 跳出迴圈是,next j 0,否則next j 會在break之前被賦值 return next 對主串s和模式串t進行kmp模式匹配 主串 par...
演算法之KMP
kmp演算法是一種字串匹配演算法,時間複雜度為 m n 個人對演算法學習還在初級階段。以前對字串匹配用暴力匹配演算法。暴力匹配演算法 兩個字串,模板串mo和文字串s。如果用暴力演算法,對於模板串mo,用i表示模板串匹配的位置。用j表示文字串匹配的位置。1,如果從一開始匹配的上,i和j同時增加。2,當...