KMP演算法之Next陣列 C

2021-08-23 12:04:14 字數 1888 閱讀 4164

這篇文章不解釋什麼是o(n)記法

kmp是乙個兩串字串比較的演算法,分別為p:模式串,s:文字串。
我的文章一般都是廢話少說,直接就進入主題。

我們假設現在需要匹配如下:

傳統的做法:逐一的遍歷s串,再遍歷p串,s[ i ]!=p[ j ](i=0,j=0),因為不相等,所以 i 會自增 1 (++),j 回溯 0,當 i = 7 發生匹配,j++(j = 1), i = 8 發生匹配 j++(j = 2), i = 9 失配 j 回溯 0

這邊p串只有三個字元,還好,但是如果p串的字元量很大,這開銷很大,因為我們要回溯p串到位置 0 然後開始新的匹配

然而kmp演算法可以根據p串提前計算好預知的回溯位置,減少我們的回溯位,減少開銷。也就是網上 所謂的next 陣列

(這裡我們不討論什麼時間複雜度,拋開這些理論,站在程式這一面來理解)

我們先看看next 陣列是怎麼計算的。假設我們現在的p不變。

然後定義乙個 int 陣列,陣列的長度的p串的長度 + 1(因為我們占用下 0 下標,並且陣列的 0 號位標識為 -1 ,1號位標識為 0 ,因為我們的回溯字元p最高就是 0)。

先上下**,然後繼續講解。

_next = new int[p.length + 1];

_next[0] = -1;

_next[1] = 0;

int i = 0;

int j = 1;

while (j < p.length)

else

}else

}

這裡的 i 表示的是字首字元,j 表示的是字尾字元。

什麼是字首,什麼是字尾?

1,2,3,4,5,6 => 3 字首 1 字尾2

=> 5 (字首1 字尾4)and (字首2,字尾3)

類似高斯先生的演算法 從1 加到 100

我們可以手動演算一遍,方便牢記

這裡的計算我並沒有 計算if (j < t.length && t[i] != t[j])這個判斷,這裡是個小優化。

因為 假設我們有一串字元s: sssssssssaaacsssssdcacaaaaagsscsssssssdac p:sssssdac

如果我們要進行匹配,我們可以大概看出,在匹配從c/g開始的時候就,會有開始的回溯,而且是乙個乙個的回溯,這樣看起來不好,因為前面的p串的 sss..是相同的,我們可以考慮next陣列保持一樣的,這樣我們就能直接回溯到指定的位置,從而減少回溯的次數。也就是if (j < t.length && t[i] != t[j])這個判斷裡面的語句了。

這裡就是next的陣列計算了。

下篇再寫後續的字元匹配

KMP演算法 next陣列

通過上文完全可以對kmp演算法的原理有個清晰的了解,那麼下一步就是程式設計實現了,其中最重要的就是如何根據待匹配的模版字串求出對應每一位的最大相同前字尾的長度。我先給出我的 1 void makenext const char p,int next 214 next q k 15 16 現在我著重講...

KMP演算法 NEXT陣列

kmp和next陣列基本上是一起用的,有了next陣列,才有kmp演算法,講道理來說這兩個都是基於最大前字尾和,也就是說需要用到kmp的時候必須先把next陣列先求出來,next陣列就是由所匹配的word的每個子串的前字尾和最大匹配得到的,說實話next陣列的演算法給優化得已經很無解了,以至於至今我...

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

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