在介紹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)其實在上面的匹配過程中,有很多比較是多餘的。在第五趟匹配失敗的時候,在第六趟,i可以保持不變,j值為2。因為在前面匹配的過程中,對於串s,已知s0s1s2s3=p0p1p2p3,又因為p0!=p1!,所以第六趟的匹配是多餘的。又由於p0==p2,p1==p3,所以第七趟和第八趟的匹配也是多餘的。在kmp演算法中就省略了這些多餘的匹配。if(j==strlen(p))
return i-strlen(p);
i=i-j+1; //
指標i回溯
}
return -1
;
}
二.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)因此kmp演算法的關鍵在於求算next陣列的值,即求算模式串每個位置處的最長字尾與字首相同的長度, 而求算next陣列的值有兩種思路,第一種思路是用遞推的思想去求算,還有一種就是直接去求解。else
if(j==strlen(p))
return i-strlen(p);
}return -1
;}
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)2.直接求解方法else
//p[j]!=p[k]
k=next[k];}}
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演算法的意思,卻說不出個究竟,所謂知其然不知其所以然是也。經過七八個小時地仔細研究,終於感覺自己能說出其所以然了,又覺得資料結構書上寫得過於簡潔,不易於初學者接...