KMP演算法深度解析

2021-08-24 18:52:49 字數 2144 閱讀 7120

摘要:kmp演算法是字串匹配的經典演算法,由於其o(m+n)的時間複雜度,至今仍被廣泛應用。大道至簡,kmp演算法非常簡潔,然而,其內部卻蘊含著玄妙的理論,以至許多人知其然而不知其所以然。本文旨在解開kmp演算法的內部玄妙所在,希望能夠有助於學習與理解。

1、kmp演算法

一種改進的字串匹配演算法,由d.e.knuth與v.r.pratt和j.h.morris同時發現,因此稱之為kmp演算法。此演算法可以在o(n+m)的時間數量級上完成串的模式匹配操作,其基本思想是:每當匹配過程中出現字串比較不等時,不需回溯指標,而是利用已經得到的「部分匹配」結果將模式向右「滑動」盡可能遠的一段距離,繼續進行比較。

2、基於有限自動機理解演算法

kmp 演算法看似簡單,其實要完全理解還是有困難的。kmp演算法其實可以看成是乙個有限自動機,分為 2 部分:第一部分自動機的構造 ( 對應一般的說法就是失效函式,轉移函式, overlap 函式 ) ,第二部分在自動機上搜尋過程。舉個例子: 目標串 t = acabaabaabcacaabc; 模式串 p=abaabcac ;根據模式串構造自動機,向前的箭頭表示搜尋前進的方向。向後的箭頭表示不匹配的回溯,即失效函式,或者狀態變遷函式。例如:

f(j=1) = 0;

f(j=2) = 0;

f(j=3) = 1;

f(j=4) = 1;

f(j=5) = 2;

f(j=6) = 0;

f(j=7) = 1;

kmp本質上是構造了dfa並進行了模擬,因此很顯然一旦從模版t構造了自動機d,用d去匹配主串s的過程就是線性的。kmp最引人入勝的地方就在於構造d的自匹配過程,它充分利用了d是乙個dag的性質,使得構造過程也是線性的。kmp演算法不需要計算變遷函式,只用到輔助陣列next,即模式串自身的特徵向量。特徵向量可以用模式與其自身進行比較,預先計算出來,它可用於加快字串匹配演算法與有限自動機匹配器的執行速度。

3、next特徵陣列構造

模式串p開頭的任意個字元,把它稱為字首子串,如p0p1p2…pm-1。在p的第i位置的左邊,取出k個字元,稱為i位置的左子串,即pi-k+1... pi-2 pi-1 pi。求出最長的(最大的k)使得字首子串與左子串相匹配稱為,在第i位的最長字首串。第i位的最長字首串的長度k就是模板串p在位置i上的特徵數n[i]特徵數組成的向量稱為該模式串的特徵向量。

可以證明對於任意的模式串p=p0p1…pm-1,確實存在乙個由模式串本身唯一確定的與目標串無關的陣列next,計算方法為:

(1) 求p0…pi-1中最大相同的字首和字尾的長度k;

(2) next[i] = k;

作為特殊情況,當i=0時,令next[i] = -1;顯然,對於任意i(0≤i 0的n[i] ,假定已知前一位置的特徵數 n[i-1]= k ;

(2) 如果pi = pk ,則n[i] = k+1 ;

(3) 當pi ≠ pk 且k≠0時,則令k = n [k -1] ; 讓(3)迴圈直到條件不滿足;

(4) 當qi ≠ qk 且k = 0時,則ni = 0;

根據以上分析,可以得到next特徵陣列的計算方法,演算法**如下:

void get_next(sstring t, int &next) else } }

文獻[5]中解釋了以上計算方法存在一定缺陷,存在多比較的情況,可對其進行修正,得到如下演算法:

void get_next(sstring t, int &next) else } }

4、演算法實現

kmp演算法的難點就是有限自動機的構造和特徵向量的計算。解決了這兩個問題後,具體匹配演算法就很簡單了。

int index_kmp(sstring s,sstring t,int pos)//繼續比較後繼字元

else j = next[j];//模式串象右移動

} if(j>t[0]) return i-t[0];//匹配成功

else return 0;

}//index_kmp

5、參考文獻

[1]

[2] 和extend-kmp演算法.html

[3] kmp演算法講義ppt(hu junfeng, peking university)

[4] 演算法導論(第32章 字串匹配)

[5] 資料結構(第4章 串)

KMP演算法解析

日期 2013年5月 1日 字串匹配是計算機的基本任務之一。舉例來說,有乙個字串 bbc abcdab abcdabcdabde 我想知道,裡面是否包含另乙個字串 abcdabd 許多演算法可以完成這個任務,knuth morris pratt演算法 簡稱kmp 是最常用的之一。它以三個發明者命名,...

KMP演算法解析

今天來說說這個難以理解的kmp演算法。之前寫過乙個模板,一直去套用,實在愧對演算法二字,今天悟一下。kmp演算法完成的任務是 給定兩個字串o和f,長度分別為n和m,判斷f是否在o中出現,如果出現則返回出現的位置。常規方法是遍歷a的每乙個位置,然後從該位置開始和b進行匹配,但是這種方法的複雜度是o n...

KMP演算法解析

kmp 演算法是用來求乙個較長字串是否包含另乙個較短字串的演算法,其中難點在於求解 next 陣列。next 陣列含義為 如果匹配到該字元時失敗,回溯的位置。straba abca cpos01 2345 67next 10 0112 01其中,next 陣列首位設定為 1,意味著首位匹配失敗時無法...