1. 程式人生 > >面向考研——計算KMP演算法中的next陣列和nextval陣列

面向考研——計算KMP演算法中的next陣列和nextval陣列

KMP演算法中,如何手動求next陣列和nextval陣列?

首先我們要理解next陣列的意義,為了實現更加高效的字元匹配,next陣列是用來尋找字串陣列內部的自身的一種規律,利用字串內部的一種相似性,來優化字串陣列匹配演算法。所以才需要計算這麼一個next陣列來幫助演算法更好的實現字串匹配。

next陣列的計算方式邏輯上稍微複雜,初學者可能很難看懂,所以首先要理解,為什麼要計算next陣列以及更加優化的nextval陣列。

假如有這樣一串字串

1 2 3 4 5 6

a a a a a a

這可以說是一個字串間規律最強的一個數組了吧,讓我們來手動模擬一下。

首先預設第一位是0,第二位是1,從第3位開始求,比較第3-1位和next[3-1]的字元是否相同,若相同,則next[3]=next[2]+1

所以第3位的值就是2.那麼依此類推就可以得到,這個字串的next陣列為

1 2 3 4 5 6

a a a a a a

0 1 2 3 4 5

總結來看就是相同就在他的next陣列值加1.

那麼有這樣一個字串那

1 2 3 4 5 6

a b c d e f

預設給出第1位為0 第二位為1 ,發現全都不一樣,可以說毫無相關性了,所以next陣列為

1 2 3 4 5 6

a b c d e f

0 1 1 1 1 1

這兩種極端情況可以讓大家初步瞭解一下計算next陣列的方法,起碼可以初步理解一下next陣列的意義。但是這還不完善。

下面介紹一到北郵2016年考研真題

1 2 3 4 5 6 7 8

a b a a b c a c

0 1 1 2 2 3 1 2

這是一個考試常見的字串,是如何計算的那?

第n位:next[n]的值來自於第n-1位的字元,通過跟第next[n-1]位字元比較,如果相同next[n]=next[n-1],如果不相同,就跟第next[next[n-1]]位的字元比較,就這樣迭代直到相同的時候,加上1,如果實在沒有,就為1.

這一段話可能很難理解,逐位分析。

讓我們從依次來看:

第3位:第2位和第1位比較,不相同 所以為1

第4位:第3位和第1位比較,相同,所以為2

第5位:第4位和第2位比較,不相同,和第1位比較,相同,所以為2

第6位:第5位和第2位比較, 相同,所以為3

第7位:第6位和第3位比較,不同,和第1位比較,不同,所以為1

第8位:第7位和第1位比較,相同,所以為2.

這就是next陣列的手動計算方法。

接下來介紹如何根據next陣列計算nextval陣列

nextval是在next陣列的基礎上優化演算法,避免不必要的浪費。其實我也不太理解nextval的具體原理,現只能介紹一下如何計算。

依舊用上面北郵的真題為例,其真題本身求的就是nextval陣列

現在我們已經有了next陣列:

1 2 3 4 5 6 7 8

a b a a b c a c

0 1 1 2 2 3 1 2

現在通過next陣列計算nextval陣列,nextval陣列與next相反,是找不同,

1 2 3 4 5 6 7 8

a b a a b c a c

0 1 1 2 2 3 1 2

0 1 0 2 1 3 0 2

第1位:必為0

第2位:第2位next值為1,所以第2位和第1位比較,不同,為第2位的next 值1

第3位:第3位next值為1,所以第3位和第1位比較,相同,因為到第1位了,所以為0

第4位:第4位next值為2,所以第4位和第2位比較,不同,就為第4位next值2

第5位:第5位next值為2,所以第5位和第2位比較,相同,則繼續,第2位和第1位不同,則為第2位的next值1

第6位:第6位next值為3,所以第6位和第3位比較,不同,就為第6位的next值3

第7位:第7位next值為1,所以第7位和第1位比較,相同,則為0

第8位:第8位next值為2,所以第8位和第2位比較,不同,則為第8位的next值2

【簡而言之】第n位nextval陣列值就是,讓第n位字元和第next[n]位比較,不同,則nextval[n]=next[n],如果相同,則比較第next[next[n]]位和第next[n]位比較,如果不同,則nextVal[n]=next[next[n]].就是這樣的計算方式。