本文適用於讀者對kmp演算法有一定的了解
void initnextarray(string p)
}
上述**是kmp演算法中next陣列的建立過程,最難理解的過程就是k = next[k];這一行**,今天給大家來解釋一下這句**背後隱藏的遞迴思想。
首先給大家捋一捋各個引數的意義
j是模式串的當前角標
k是在模式串當前角標之前已經匹配的字首字尾的長度。
next[j]表示在角標j之前已經匹配的字首字尾的長度。
演算法思想:利用當前已知的next[j]和k並結合p模式串特點推算出next[j+1]
已知的next[j]和k意味著前提為p[0]p[2]…p[k-1] == p[j-k]p[j-k+1]…p[j-1]
推算next[j+1]則要使用字元p[j]與字元p[k]作比較。
如果p[k] == p[j];
則可得 p[0]p[2]…p[k-1]p[k] == p[j-k]p[j-k+1]…p[j-1]p[j];
即執行next[++j] = ++k; 已經匹配的前字尾長度k加1之後賦給角標為j+1的next陣列的元素。注意此時j這個游標後移了一位,意味著可以進行下乙個next元素的求解。
如果 p[k] != p[j]
那麼該怎麼辦?為什麼k = next[k]?
既然找不到最大匹配前字尾長度,我們就應該退而求其次,找到乙個相對較短的匹配前字尾,而且這個next[j+1]的值是不固定的
提供下面簡單的三種情況:
上述標紅內容就是在不匹配發生時,next[j+1]的取值各不相同,而k = next[k]可以很好的識別出來;
前提是已知next[j]和k的值,求next[j+1]的值
有前提可知p[0]p[2]…p[k-1] == p[j-k]p[j-k+1]…p[j-1]
但是p[k] != p[j],那我們就應該找稍微短一些的匹配前字尾串
next[k]的意義是在模式串的k角標之前的匹配的前字尾串的長度
也就是存在乙個k』,使得p[0]p[1]…p[k』-1] == p[k-k』]p[k-k』+1]…p[k-1]
結合前提推得p[0]…p[k』-1] == p[j-k』]p[j-k』-1]…p[j-1];
詳細分析可以結合理解:
上圖最後一部分的紅色部分即為更短的匹配字首字尾,k = next[k]這句話的意義就可以明白了,注意這時候j並沒有向後移動,也就意味著下一次迴圈中p[j]和p[k』]需要繼續進行比較,如果還是不相等,那麼就要繼續k = next[k];(即k = next[next[k』]])遞迴就體現在這裡,如果一直不相等,最後的k會變為-1,那麼這個時候」遞迴」就結束了,執行next[++j] = ++k(k有初始化為0,next[j+1]也被賦值為0,並且j游標也後移了一位,可以繼續初始化next陣列了)。
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陣列的求法。位置i01 2345 6789 1011 1213 1415 字首next i 00 0012 3123 4567 40子串a gcta gcag ctag ctg 申明一下 下面說的對稱不是中心對稱,而是中心字元塊對稱,比如不是abccba,而是abca...