KMP演算法最詳細分析!!
1.首先明確,next陣列存在的意義是什麼:
示例如下:
主串: a b a b c a b c a c b a b
模式串: a b c a c
匹配過程如下:
第一次匹配:
這個時候,如果不用KMP,而是用BF,那麼我們的做法很明顯:
嘗試模式串的第一個字元和主串的第二個字元進行匹配。
很明顯,這是多餘的,這是肯定不成立的,而next陣列直接告訴我們,跳過這一步,直接如下
這就是next的作用,如果還不明顯,你再看上圖,模式串的第五位是c和主串相對位置的b不匹配,那麼按照BF演算法,我們需要
再用主串的第四位和模式串的第一位比較,但是,很舒服,next陣列告訴我們不用這樣,直接如下
以上就是next的作用,跳過無用的匹配。
2.思考,next為什麼可以這樣做呢?
首先,什麼是next陣列:
上述模式串的next陣列如下:
a b c a c
0 1 1 1 2
簡而言之,每個字母x對應的next陣列值是這樣的出來的:x前的子串和主串的前幾個字母相同,則只需要比較x和主串的第y個元素就好了,那麼這個y就是next[x的索引]的值。
下面引入求next陣列的演算法:
next儲存起始從1開始
void GetNext(string s,int next[])//s是模式串
{
int i=1,j=0;next[1]=0;
while(i<s.length()-1){
if(j==0||s[i]==s[j]){
i++;j++;
next[i]=j;
}
else{
j=next[j];//這一步很關鍵,他起到的作用就是剛才上面講到的配對失敗之後,直接跳到指定的位置
}
}
}
既然已經得到next陣列了,那麼實際操作就很簡單了,附上KMP程式碼:
int KMP(string s,string t,int pos)//引數分別是主串,模式串,求模式串在主串第pos個字元之後的位置
{
int i=pos,j=1;
while(i<s.length()&&j<t.length()){
if(j==0||s.data[i]==t.data[j]){
i++;j++;//均後移一位
}
else j=next[j];//找到適當的位置
}
if(j>t.length())return i-t.length();//匹配成功
else return -1;
}