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

2021-10-17 10:28:45 字數 1871 閱讀 5528

kmp演算法與bf演算法的比較:

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

kmp演算法:

對bf進行思考後,我們會發現其實i可以不用回溯,只需要回溯j就可以完成匹配,因為我們完全可以只移動j來匹配所有的過程,例如下圖時,我們可以不移動i,只將j移動到子串第三位;

但是如果是讓我們自己來匹配的話,我們肯定不會這麼蠢,我們肯定不會把j移動到第三位,而是把j移動到第一位,為什麼呢?我們自己也說不上來,這只是我們主觀的巧合嗎?再如下圖,當我們遇到這種情況時也不會把j移到子串第三位,而是依然把j移到子串第1位,

為什麼呢?因為我們知道子串第一位是a,而主串已經和子串匹配契合的部分中只有第一位是a,也就是說子串中j以前的部分中只有乙個a,;再如下圖所示情況,我們會將j移動到子串第二位來進行匹配,為什麼?似乎是因為j之前的子串部分中有兩個a;

從上面3個例子我們可以看出j的移動是有技巧的,那我們不妨設當i與j不匹配時,j應移到子串的下乙個位置為k;我們動用一下逆向思維,再來看下圖,如果兩個矩形框起來的兩個串是一樣的,那麼

對於第乙個矩形框中的串有什麼要求,是不是要求自己的後2兩位與自己的前兩位是相同的,那麼相應的,如果乙個串的後n位與自己的前n位相同,再在後面跟上一些未知的數是不是有可能在後乙個矩形框裡可能產生與前乙個矩形框一樣的串;好,現在我們再看下面的例子:

這時,i與j不匹配了,我們是不是應該將j移動到子串第二位,那麼規律出來了,假如下次j應移動到子串的k位置,那麼應滿足:串t[0]—t[k-1]應與串t[j-k]—t[j-1]相同;

那麼大概清楚了k具有什麼作用和性質,而next陣列就是存下乙個個k的值,比如next[3]的含義就是指當i=j=3時不匹配了,j下一步應移動到子串的k位置的k的值,那麼假如我們可以求出next陣列,那麼是不是就可以在i與j不匹配時就直接把j移動到next[j]而避免掉無用的移法。那麼怎麼求next陣列,求next陣列其實就是求乙個個k值;

首先當j==0時:此時應當將i往後移動一位,j不動,那麼我們任意記乙個-1作為k值來和其他只移動j的k值進行區分;

當j==1時:此時j肯定移動到0位置,那麼next[1]=0;

當j==2時:那麼就要看t[0]與t[1]是否相同,如果相同,則next[2]=1;否則next[2]=0;

當j==n時:那麼所求的k就是滿足j前面k位與子串前k位相同即t[0~k-1]==t[j-k~n-1],而反觀next[n-1],(令m=next[n-1])其含義表示t[0~m-1]==t[j-m~n-2],那麼會發現當t[n]==t[k]時,next[n]=m+1;假如不相等,那麼第k位還有可能與主串i位相匹配,與判斷第n-1位時類似,即next[n]=next[m]+1;

那麼,到現在,我們已經可以求出next陣列了,next陣列是只與子串本身的前後相似性相關的陣列,求解出來後可以得到i與j不匹配時j應移動至的最有效的位置,可以大幅減少j的移動次數,提高效率。

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求法

定義 1 next 0 1 意義 任何串的第乙個字元的模式值規定為 1。2 next j 1 意義 模式串t中下標為j的字元,如果與首字元 相同,且j的前面的1 k個字元與開頭的1 k 個字元不等 或者相等但t k t j 1 k 如 t abcabcad 則next 6 1,因t 3 t 6 3 ...