初探KMP演算法之next nextval

2021-07-25 15:29:44 字數 2442 閱讀 3222

這種演算法是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,當...