KMP演算法詳解

2021-06-22 00:09:01 字數 3759 閱讀 2017

在介紹kmp演算法之前,先介紹一下bf演算法。

一.bf演算法

bf演算法是普通的模式匹配演算法,bf演算法的思想就是將目標串s的第乙個字元與模式串p的第乙個字元進行匹配,若相等,則繼續比較s的第二個字元和p的第二個字元;若不相等,則比較s的第二個字元和p的第乙個字元,依次比較下去,直到得出最後的匹配結果。

舉例說明:

s:  ababcababa

p:  ababa

bf演算法匹配的步驟如下

i=0                                   i=1                             i=2                         i=3                          i=4

第一趟:ababcababa         第二趟:ababcababa      第三趟:ababcababa    第四趟:ababcababa    第五趟:ababcababa

ababa                            ababa                          ababa                        ababa                       ababa

j=0                                   j=1                            j=2                         j=3                         j=4(i和j回溯)

i=1                                 i=2                           i=3                            i=4                        i=3

第六趟:ababcababa         第七趟:ababcababa       第八趟:ababcababa     第九趟:ababcababa   第十趟:ababcababa

ababa                              ababa                           ababa                        ababa                        ababa

j=0                                  j=0                           j=1                           j=2(i和j回溯)            j=0

i=4                                    i=5                          i=6                           i=7                          i=8

第十一趟:ababcababa       第十二趟:ababcababa    第十三趟:ababcababa   第十四趟:ababcababa   第十五趟:ababcababa

ababa                               ababa                           ababa                          ababa                          ababa

j=0                                    j=0                         j=1                            j=2                         j=3

i=9

第十六趟:ababcababa

ababa

j=4(匹配成功)

**實現:

int bfmatch(char *s,char *p)

if(j==strlen(p))

return i-strlen(p);

i=i-j+1; //

指標i回溯

}

return -1

;

}

其實在上面的匹配過程中,有很多比較是多餘的。在第五趟匹配失敗的時候,在第六趟,i可以保持不變,j值為2。因為在前面匹配的過程中,對於串s,已知s0s1s2s3=p0p1p2p3,又因為p0!=p1!,所以第六趟的匹配是多餘的。又由於p0==p2,p1==p3,所以第七趟和第八趟的匹配也是多餘的。在kmp演算法中就省略了這些多餘的匹配。

二.kmp演算法

kmp演算法之所以叫做kmp演算法是因為這個演算法是由三個人共同提出來的,就取三個人名字的首字母作為該演算法的名字。其實kmp演算法與bf演算法的區別就在於kmp演算法巧妙的消除了指標i的回溯問題,只需確定下次匹配j的位置即可,使得問題的複雜度由o(mn)下降到o(m+n)。

在kmp演算法中,為了確定在匹配不成功時,下次匹配時j的位置,引入了next陣列,next[j]的值表示p[0...j-1]中最長字尾的長度等於相同字串行的字首。

對於next陣列的定義如下:

1) next[j] = -1  j = 0

2) next[j] = max(k): 03) next[j] = 0  其他

如:p      a    b   a    b   a

j      0    1   2    3   4

next    -1   0   0    1   2

即next[j]=k>0時,表示p[0...k-1]=p[j-k,j-1]

因此kmp演算法的思想就是:在匹配過程稱,若發生不匹配的情況,如果next[j]>=0,則目標串的指標i不變,將模式串的指標j移動到next[j]的位置繼續進行匹配;若next[j]=-1,則將i右移1位,並將j置0,繼續進行比較。

**實現如下:

int kmpmatch(char *s,char *p)

else

if(j==strlen(p))

return i-strlen(p);

}return -1

;}

因此kmp演算法的關鍵在於求算next陣列的值,即求算模式串每個位置處的最長字尾與字首相同的長度, 而求算next陣列的值有兩種思路,第一種思路是用遞推的思想去求算,還有一種就是直接去求解。 

1.按照遞推的思想:

根據定義next[0]=-1,假設next[j]=k, 即p[0...k-1]==p[j-k,j-1]

1)若p[j]==p[k],則有p[0..k]==p[j-k,j],很顯然,next[j+1]=next[j]+1=k+1;

2)若p[j]!=p[k],則可以把其看做模式匹配的問題,即匹配失敗的時候,k值如何移動,顯然k=next[k]。

因此可以這樣去實現:

void getnext(char *p,int *next)

else

//p[j]!=p[k]

k=next[k];}}

2.直接求解方法

void getnext(char *p,int *next)

else

if(i==1

)

else

}if(j==0

) next[i]=0

; }

}}bool equals(char *p,int i,int j) //

判斷p[0...j-1]與p[i-j...i-1]是否相等

return

true;}

本文出處:

附加參考部落格:

KMP演算法詳解

模式匹配的kmp演算法詳解 這種由d.e.knuth,j.h.morris和v.r.pratt同時發現的改進的模式匹配演算法簡稱為kmp演算法。大概學過資訊學的都知道,是個比較難理解的演算法,今天特把它搞個徹徹底底明明白白。注意到這是乙個改進的演算法,所以有必要把原來的模式匹配演算法拿出來,其實理解...

KMP演算法詳解

kmp演算法即knuth morris pratt演算法,是模式匹配的一種改進演算法,因為是名字中三人同時發現的,所以稱為kmp演算法。因為偶然接觸到有關kmp的問題,所以上網查了一下next陣列和 nextval陣列的求法,卻沒有找到,只有在csdn的資料檔案裡找到了next陣列的簡單求法 根據書...

KMP演算法詳解

相信很多人 包括自己 初識kmp演算法的時候始終是丈二和尚摸不著頭腦,要麼完全不知所云,要麼看不懂書上的解釋,要麼自己覺得好像心裡了解kmp演算法的意思,卻說不出個究竟,所謂知其然不知其所以然是也。經過七八個小時地仔細研究,終於感覺自己能說出其所以然了,又覺得資料結構書上寫得過於簡潔,不易於初學者接...