1. 程式人生 > >KMP模式匹配演算法中next和nextval的求解(轉)

KMP模式匹配演算法中next和nextval的求解(轉)

KMP演算法相關

轉載自:http://blog.sina.com.cn/s/blog_85b0ae450101j2iy.html

KMP演算法由兩部分組成:

第一部分,計算模式串的next或nextval陣列。

第二部分,利用計算好的模式串的nextval陣列,進行模式匹配。

KMP演算法中有next陣列和nextval陣列之分。他們代表的意義和作用完全一樣,完全可以混用。

 唯一不同的是,next陣列在一些情況下有些缺陷,而nextval是為了彌補這個缺陷而產生的。

一、求解next

步驟:

next陣列值的程式設計求解方法:首先可以肯定的是第一位的next值為0,第二位的next值為1,後面求解每一位的next值時,根據前一位進行比較。首先將前一位與其next值對應的內容進行比較,如果相等,則該位的next值就是前一位的next值加上1;如果不等,向前繼續尋找next值對應的內容來與前一位進行比較,直到找到某個位上內容的next值對應的內容與前一位相等為止,則這個位對應的值加上1即為需求的next值;如果找到第一位都沒有找到與前一位相等的內容,那麼需求的位上的next值即為1。

舉例:

模式串  a  b a  a  b c  a  c
next值  0  1 1  2  2 3  1  2
1.前兩位必為0,1。
2.計算第三位的時候,看第二位b的next值,為1,則把b和1對應的a進行比較,不同,則第三位a的next的值為1,因為一直比到最前一位,都沒有發生比較相同的現象。
3.計算第四位的時候,看第三位a的next值,為1,則把a和1對應的a進行比較,相同,則第四位a的next的值為第三位a的next值加上1,為2。因為是在第三位實現了其next值對應   
的值與第三位的值相同。
4.計算第五位的時候,看第四位a的next值,為2,則把a和2對應的b進行比較,不同,則再將b對應的next值1對應的a與第四位的a進行比較,相同,則第五位的next值為第二位b的   
next值加上1,為2。因為是在第二位實現了其next值對應的值與第四位的值相同。
5.計算第六位的時候,看第五位b的next值,為2,則把b和2對應的b進行比較,相同,則第六位c的next值為第五位b的next值加上1,為3,因為是在第五位實現了其next值對應的   
值與第五位相
6.計算第七位的時候,看第六位c的next值,為3,則把c和3對應的a進行比較,不同,則再把第3位a的next值1對應的a與第六位c比較,仍然不同,則第七位的next值為1。
7.計算第八位的時候,看第七位a的next值,為1,則把a和1對應的a進行比較,相同,則第八位c的next值為第七位a的next值加上1,為2,因為是在第七位和實現了其next值對應的值與第七位相同。

二、求解nextval:

求nextval陣列值有兩種方法,一種是不依賴next陣列值直接用觀察法求得,一種方法是根據next陣列值進行推理,兩種方法均可使用,視更喜歡哪種方法而定。
 
本文主要分析nextval陣列值的第二種方法:

  模式串    a b a a b c a c

  next值     0 1 1 2 2 3 1 2

  nextval值     0 1 0 2 1 3 0 2



  1.第一位的nextval值必定為0,第二位如果於第一位相同則為0,如果不同則為1。

  2.第三位的next值為1,那麼將第三位和第一位進行比較,均為a,相同,則,第三位的nextval值為0。

  3.第四位的next值為2,那麼將第四位和第二位進行比較,不同,則第四位的nextval值為其next值,為2。

  4.第五位的next值為2,那麼將第五位和第二位進行比較,相同,第二位的next值為1,則繼續將第二位與第一位進行比較,不同,則第五位的nextval值為第二位的next值,為1。

  5.第六位的next值為3,那麼將第六位和第三位進行比較,不同,則第六位的nextval值為其next值,為3。

  6.第七位的next值為1,那麼將第七位和第一位進行比較,相同,則第七位的nextval值為0。

  7.第八位的next值為2,那麼將第八位和第二位進行比較,不同,則第八位的nextval值為其next值,為2。

三、next和nextval比較

Next陣列的缺陷舉例如下:

比如主串是“aab…..” 省略號代表後面還有字元。

 模式串“aac”

通過計算aac的next陣列為012(另外,任何字串的第二位字元的next總是1,因此你可以認為他固定為1)

當模式串在字元c上失配時,會跳到第2個字元,然後再和主串當前失配的字元重新比較,即此處用模式串的第二個a和主串的b比較

即aab->aac

顯然a也不等於b。然後會跳到1,接著比,然後又失配,直到最後才使主串後移一位。

而“aac”的nextval陣列為002當在c失配時會跳到2,若還失配就直接跳到0,比next陣列少比較了1次。

在如果模式串很長的話,那可以省去很多比較,因此你應該使用nextval陣列。