1. 程式人生 > >KMP演算法--next陣列的解釋

KMP演算法--next陣列的解釋

前言

KMP演算法,我個人感覺還有是有寫難度的,我想了兩天才大概想明白(我想說的是,你們也可能想了好久還是想不明白,沒事,別放一下,有空了就想一想,一定要一鼓作氣拿下它)。其主要就是那個所謂的 next[ ] 陣列的構建,而其關鍵又是這一步 k=next[k-1],這一步想通了就沒有什麼難的了。

參考文章


可以先參考一下這兩篇文章,能明白了其實就不用往下看了,我這裡主要是對這兩篇文章的理解,把其中關鍵的部分做了說明。
http://blog.51cto.com/13577765/2064490 (如有侵權,請聯絡我刪除) 這篇文章的那個模式字串的例子舉的挺好的,大家可以參考一下。在這裡我也貼出來吧
在這裡插入圖片描述

http://www.cnblogs.com/c-cloud/p/3224788.html (如有侵權,請聯絡我刪除) 這篇文章有對KMP演算法的詳細解釋。

先看程式碼在解釋

寫在前面

一定要理解 K 的含義和用 K-1 做下標到底意味著什麼。
還有最重要的:::K=next[k-1] 其實是用到了遞迴的思想,一定要記住他用的是 遞迴 的思想,程式碼要是看不明白了,就回來看看這句話。

next陣列的求解過程

void makeNext(const char P[],int next[])
{
    int q,k;//q:模版字串下標;k:最大前後綴長度
    int m = strlen
(P); next[0] = 0;//模版字串的第一個字元的最大前後綴長度為0 for (q = 1,k = 0; q < m; ++q)//for迴圈,從第二個字元開始,依次計算每一個字元對應的next值 { while(k > 0 && P[q] != P[k])//遞迴的求出P[0]···P[q]的最大的相同的前後綴長度k k = next[k-1];//不理解沒關係看下面的分析,這個while迴圈是整段程式碼的精髓所在,確實不好理解 if (P[q] == P[k])//如果相等,那麼最大相同前後綴長度加1
{ k++; } next[q] = k; } }

對 k=next[k-1] 詳解

先貼出我的手稿
在這裡插入圖片描述
字跡可能不太清楚(很難看,大家將就一下),我把它再寫一遍,主要是看圖,而且一定要自己動手寫一寫這個字串,就會瞬間明白 k=next[k-1]。

手稿說明

在P[q]=P[k]不相等時,即產生失配後該怎麼辦,讓K–嗎?(我看到過有些文章這裡寫的是 K–,才會有這個提問,而且我一開始也是認為K–也可以,一開始也成功了,那是因為你找的字串很特殊造成的假象,一旦你明白了k=next[k-1]這條語句的真正含義,就會發現 K-- 所表達的含義很突兀,即不知道 K-- 要表達什麼)
顯然不對,而是應該重新從P[0]開始找,再找到一個適配點(而且要保證適配後K值儘量最大),而以K=next[k-1]為下標的下一個元素就是剛好要找的,即第一個 {} 後面的 t ,而為了簡化這裡就找了一次就找了也有助於大家的理解。

重要的事情

一定要親自動手寫寫這個字串,動筆嘩啦嘩啦,看看這個K值是怎麼變化的,別老盯著程式碼看,看不出花來。一旦動手寫,很容易明白的。

具體的完整程式碼這裡就不貼了,這裡只介紹最難理解的 next 陣列的構建,想看完整程式碼的,你們可以看靠我給出的第二個連結。

結語

有些不對或者不太清楚的地方,歡迎大家指正,及時修改,以免誤導了別人。很感謝上面兩篇文章的作者,讓我明白了這個演算法,真的感謝。後續會把完整程式碼補全,可能後面還會寫一個KMP的優化演算法。