1. 程式人生 > >KMP中next和nextval演算法細節

KMP中next和nextval演算法細節

轉自豆瓣大神總結,由於暫時還在學習階段,沒有自己的理解,還是直接搬運過來吧。

資料結構中,在串的這節,其實難度不大,關鍵是模式匹配的問題,而在模式匹配中要數KMP演算法的難度最大,而KMP的next&nextval的計算則成了學習的重中之重。面對好多學校的教程跳過不講,而教材裡的公式又難以理解,好多自學的同仁們往往在這上面費盡心思。現在把我的學習心得發出來共享,如有錯誤,還望不吝指正。呵呵~
T : 1 2 3 4 5 6 7
串 : a b c a b a a
next : 0 1 1 1 2 3 2
nextval:0 1 1 0 1 3 2
以上面的為例,先說next。next值本身的含義即是當進行匹配的模式串發生失配後,失配的這一字元再次進行匹配時要與哪個字元再進行比較?我們可以理解為這次配不上,那我下次和誰比?這樣,next的值就與T發生了關係,表示了字元的比較位置。T就是元素的位置。
開始不用說,a前面沒有,就是0,b要和a比,a的位置是1,b就是1。簡單說,開頭兩個肯定是0,1!
第三個,c,c的前面是b,bc無法與開頭的a比,所以c還是要單獨找位於1的a,所以它也是1。
第四個,a,和第三個c一樣,沒有可以滿足ca的字串,最後a只能自己和第一個a配,它也是1。
第五個,b,看b前面,正好,a可以與開頭的a對上,而第五個b正好在2的位置,所以b就是2。
第六個,a,看a前面,發現,a前面的ab可以與開頭的ab對上,對上後,第六個a在位置3,所以就是3。
第七個,a,看a前面,只有a能夠與開頭配上,而“baa”則不行,所以它只有為2。
由此可以看出,next的計算,實際上就是計算當前字元以及當前字元前面的字元與開頭匹配成功後,當前字元的最終位置,如果不成,就只能單獨找第1個,所以它的值只能為1。
再看nextval,nextval是建立在next的基礎上,我自己是這樣理解的:同樣是匹配,如果匹配成功,則位於後面的字元的next繼承匹配成功的字元的nextval值,如果不成,保持不變。
以上為例:
第二位置的b按next值與開頭a比較,不符,nextval不變,為1。
第三位置的c同樣與1位置的a比較,不同,不變還是為1。
第四位置的a按next值與開頭a比較,相同,繼承開頭a的nextval值,0。
第五位置的b按next值與二位置的b比較,相同,繼承b的nextval值,1。
第六位置的a按next值與三位置c比較,不同,保持不變,3。
第七位置的a按next值與二位置b比較,不同,保持不變,2。
以上就是我的理解,當然,這是完全拋開了演算法的描述,按照單純計算next&nextval的值。關於演算法,還是要好好理解的。
下面給出一個長的,加深印象。
123456789……
abcaabbabcabaacbacba
next:
01112231234532211211


nextval:
01102130110532210210