之前看到資料結構中字串的模式匹配時,花了半天的時間,才把kmp演算法中的next函式整明白了,結果過了幾天在看到這時,只記得next[j+1]=next[j]+1,可是有時候能套公式正確算出,有時候就算不對,所以今天再重新理一遍思路,順便記錄下來,防止哪天腦子再短路了,又不知道怎麼求解的了。
先看看next資料值的求解方法
位序 1 2 3 4 5 6 7 8 9
模式串 a b a a b c a b c
next值 0 1 1 2 2 3 1 2 3
next陣列的求解方法是:
1.第一位的next值為0
2.第二位的next值為1
後面求解每一位的next值時,根據前一位進行比較
3.第三位的next值:第二位的模式串為b ,對應的next值為1;將第二位的模式串b與第一位的模式串a進行比較,不相等;則第三位的next值為1(其他情況均為1)
4.第四位的next值:第三位的模式串為a ,對應的next值為1;將第三位的模式串a與第一位的模式串a進行比較,相同,則第四位的next值得為1+1=2
5.第五位的next值:第四位的模式串為a,對應的next值為2;將第四位的模式串a與第二位的模式串b進行比較,不相等;第二位的b對應的next值為1,則將第四位的模式串a與第一位的模式串a進行比較,相同,則第五位的next的值為1+1=2
6.第六位的next值:第五位的模式串為b,對應的next值為2;將第五位的模式串b與第二位的模式中b進行比較,相同,則第六位的next值為2+1=3
7.第七位的next值:第六位的模式串為c,對應的next值為3;將第六位的模式串c與第三位的模式串a進行比較,不相等;第三位的a對應的next值為1,
則將第六位的模式串c與第一位的模式串a進行比較,不相同,則第七位的next值為1(其他情況)
8.第八位的next值:第七位的模式串為a,對應的next值為1;將第七位的模式串a與第一位的模式串a進行比較,相同,則第八位的next值為1+1=2
9.第八位的next值:第八位的模式串為b,對應的next值為2;將第八位的模式串b與第二位的模式串b進行比較,相同,則第九位的next值為2+1=3
如果位數更多,依次類推
kmp演算法的關鍵在於求算next陣列的值,即求算模式串每個位置處的最長字尾與字首相同的長度,下面按照遞推的思想總結一下求解next陣列:
根據定義next[1]=0,假設next[j]=k, 即p[1...k-1]==p[j-k,j-1]
1)若p[j]==p[k],則有p[1..k]==p[j-k,j],很顯然,如果next[j]=k; 則next[j+1]=next[j]+1=k+1;否則
next[j+1]=k+1!=next[j]+1;(當初就想著記公式簡單可以直接套用呢,結果只記住next[j+1]=next[j]+1以至於後來迷糊了)
2)若p[j]!=p[k],則可以把其看做模式匹配的問題,即匹配失敗的時候,k值如何移動,顯然k=next[k]。
因此可以這樣去實現:
void getnext(char *p,int *next)
{ int j,k;
next[1]=0;
j=1;
k=0;
while(j
kmp模式匹配演算法改進:
後來有人發現其實kmp演算法還是有缺陷的,比如主串s=「aaaabcde」,子串t=「aaaaag」,其next陣列為012345;當i=5 ,j=5是「b」與「a」不匹配,此時j=next[5]=4,又發現j=4時,「b」與「a」不匹配,依次類推,直到j=next[1]=0;此時i++,j++,i=6,j=1從而我們發現中間有多餘的判斷,由於子串t中第2、3、4、5位置的字元都與首位的「a」相同,即可以用首位next[1]的值去取代與它字元相等的後續next[j]的值,即next陣列改為000005,此時由i=5,j=5時「b」與「a」不匹配,此時j=next[5]=0;此時i++,j++得到i=6,j=1,即可省去中間的多餘判斷。因此我們需要改進next函式的求解方法。
/* 求模式串t的next函式修正值並存入陣列nextval */
void get_nextval(string t, int *nextval)
{ int i,j;
i=1;
j=0;
nextval[1]=0;
while (i
資料結構 KMP演算法
求串的模式值next n 定義 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...
資料結構 KMP演算法
在我的理解,kmp演算法最核心的同時最難理解的是這個next 函式。但是,next 的值是挺好求的,難在哪呢?這個函式難在邏輯。理解起來很費勁,但真的很好用,並且這個函式的結果很好求。例如求模式串t ababaaa 的next j 的函式值 是這樣的,當j 0,next 0 1,對於任何子串,第乙個...
資料結構 KMP演算法
要完善乙個string字串類,那麼實現查詢子串的功能是必不可少的,實現子串查詢可以使用樸素演算法,每次匹配乙個字元後向右移動乙個位置,這樣執行下來效率是比較低的,所以就有了kmp演算法,它能夠準確的知道當前字元不匹配後字串應該向右移動多少位,由於剛接觸kmp演算法,所以很多還明白的不是很透徹,在此記...