如“aba”,他的前綴有“a”和“ab”,他的后綴有“ab”和“a”,所以最長的公共前后綴的長度為1。
接下來觀察ababacab的所有前綴的最長公共前后綴的長度。(如下圖)
我們發現最長公共前后綴的長度都是連續的數字如1,2,3。
簡單解釋一下,以abab舉例子,他的最長公共前后綴的長度是2,“ab”,前綴中第三個字母是“a”,所以如果想在結尾加一個字母使最長公共前后綴的長度邊長就只能在結尾加“a”。所以前i個字母最長公共前后綴的長度是可以從前i-1個字母的最前公共前后綴推出來的。
那么是否代表每次匹配失敗的時候最長公共前后綴的長度就為0呢?答案是否定的。如下圖,最后一個字母a並沒有使最長公共前后綴的長度加1,但也沒有變成0,因為和第一個字母是相同的。
所以如果不能匹配到的時候不能直接寫成0而是要找到他的上一個匹配點。
代碼:因為這個算法為kmp算法服務,所以我們認為第一個數字為-1,並把所有數字向后移動一位(求最長公共前后綴的精髓就是我自己匹配我自己)
void kmp_per(char x[],int m,int next[]){ int i,j; j=next[0]=-1; i=0; while(i<m){ while(-1!=j&&x[i]!=x[j])j=next[j]; next[++i]=++j; } }
因為每次匹配失敗的時候我們都要找到next[next[...next[i]]],所以可以在這里優化時間復雜度。
/* kmpnext[]的意思就是next[next[...next[]]]. */ void kmp_per(char x[],int m,int kmpnext[]){ int i,j; j=kmpnext[0]=-1; i=0; while(i<m){ while(-1!=j&&x[i]!=x[j])j=kmpnext[j]; if(x[++i]==x[++j])kmpnext[i]=kmpnext[j]; else kmpnext[i]=j; } }