kmp演算法最難懂的就是next陣列的求法。
位置i01
2345
6789
1011
1213
1415
字首next[i]00
0012
3123
4567
40子串a
gcta
gcag
ctag
ctg 申明一下:下面說的對稱不是中心對稱,而是中心字元塊對稱,比如不是abccba,而是abcabc這種對稱。
(1)逐個查詢對稱串。
這個很簡單,我們只要迴圈遍歷這個子串,分別看前1個字元,前2個字元,3個... i個 最後到15個。
第1個a無對稱,所以對稱程度0
前兩個ag無對稱,所以也是0
依次類推前面0-4都一樣是0
前5個agcta,可以看到這個串有乙個a相等,所以對稱程度為1前6個agctag,看得到ag和ag對成,對稱程度為2
這裡要注意了,想是這樣想,程式設計怎麼實現呢?
只要按照下面的規則:
a、當前面字元的前乙個字元的對稱程度為0的時候,只要將當前字元與子串第乙個字元進行比較。這個很好理解啊,前面都是0,說明都不對稱了,如果多加了乙個字元,要對稱的話最多是當前的和第乙個對稱。比如agcta這個裡面t的是0,那麼後面的a的對稱程度只需要看它是不是等於第乙個字元a了。
b、按照這個推理,我們就可以總結乙個規律,不僅前面是0呀,如果前面乙個字元的next值是1,那麼我們就把當前字元與子串第二個字元進行比較,因為前面的是1,說明前面的字元已經和第乙個相等了,如果這個又與第二個相等了,說明對稱程度就是2了。有兩個字元對稱了。比如上面agctag,倒數第二個a的next是1,說明它和第乙個a對稱了,接著我們就把最後乙個g與第二個g比較,又相等,自然對稱成都就累加了,就是2了。
c、按照上面的推理,如果一直相等,就一直累加,可以一直推啊,推到這裡應該一點難度都沒有吧,如果你覺得有難度說明我寫的太失敗了。
當然不可能會那麼順利讓我們一直對稱下去,如果遇到下乙個不相等了,那麼說明不能繼承前面的對稱性了,這種情況只能說明沒有那麼多對稱了,但是不能說明一點對稱性都沒有,所以遇到這種情況就要重新來考慮,這個也是難點所在。
(2)回頭來找對稱性
這裡已經不能繼承前面了,但是還是找對稱成都嘛,最愚蠢的做法大不了寫乙個子函式,查詢這個字串的最大對稱程度,怎麼寫方法很多吧,比如查詢出所有的當前字串,然後向前走,看是否一直相等,最後走到子串開頭,當然這個是最蠢的,我們一般看到的kmp都是優化過的,因為這個串是有規律的。
在這裡依然用上面表中一段來舉個例子:
位置i=0到14如下,我加的括號只是用來說明問題:
(a g c t a g c )( a g c t a g c) t
我們可以看到這段,最後這個t之前的對稱程度分別是:1,2,3,4,5,6,7,倒數第二個c往前看有7個字元對稱,所以對稱為7。但是到最後這個t就沒有繼承前面的對稱程度next值,所以這個t的對稱性就要重新來求。
這裡首要要申明幾個事實
1、t 如果要存在對稱性,那麼對稱程度肯定比前面這個c 的對稱程度小,所以要找個更小的對稱,這個不用解釋了吧,如果大那麼t就繼承前面的對稱性了。
2、要找更小的對稱,必然在對稱內部還存在子對稱,而且這個t必須緊接著在子對稱之後。
附上**
#include#include#include #include#include#includeusing namespace std;
void fun();
int main()
void fun()
else
}for(i=1;i
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陣列解析
接上篇 next 陣列 主要記錄 子串 的 每乙個字首 按順序 的 最長匹配真前字尾 的長度。這裡講一下 求解原理。陣列從零開始,第乙個數 1 代表不存在 有的以 0 為起點代表空,這不矛盾,全加1 即為此格式 此陣列是一點點增長的,下乙個資料依賴之前的資料。舉例子來描述原理 當新的最後乙個字母過來...