天天看點

c語言資料結構kmp中next計算,資料結構——關于KMP算法中next函數的詳細解析

以前看到資料結構中字元串的模式比對時,花了半天的時間,才把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

{

if(k==0||p[j]==p[k]) //比對的狀況下,p[j]==p[k],next[j+1]=k+1;

{

j++;

k++;

next[j]=k;

}

else //p[j]!=p[k],k=next[k]

k=next[k];

}

}

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中第二、三、四、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函數的求解方法。spa

void get_nextval(String T, int *nextval)

{

int i,j;

i=1;

j=0;

nextval[1]=0;

while (i

{

if(j==0 || T[i]== T[j])

{

++i;

++j;

if (T[i]!=T[j])

nextval[i] = j;

else

nextval[i] = nextval[j];

}

else

j= nextval[j];

}

}