next陣列兩種求法

2021-08-25 11:24:56 字數 4523 閱讀 5413

一、說明

(1)看到網上同乙個字串求 next 陣列的值有兩種,一種是 -1 開頭,一種是 0 開頭,雖然有差別,但是以 0 開頭的next陣列的每一項都比以 -1 開頭的next陣列的對應項大1,所以,具體是以 0 開頭還是以 -1 開頭看需要吧,演算法都是一樣的.kmp 的原始** (k,m,p 三個傢伙寫的原文)中是以 0 開頭的,所以下面的寫法是以 0 開頭的. 

(2)關於 next 陣列的求法,網上能找到很多流行簡潔的寫法,也有很多文章對簡潔**講解得非常細緻,然而本文並不是對流行演算法的剖析,而只是記錄一下自己比較喜歡的計算方法,並用**實現一下.

二、求法的文字描述

(1)第一種求法:根據前乙個字元的next值求字串記作 p;next 陣列記作 next;

約定:1)第乙個字母的 next 值置 0 (next[1] = 0),第二個字母的 next 值置 1(next[2] = 1) ; 

2)從第 3 個開始,計算第 i 個位置的 next 值時,檢查

p[i-1]== p[next[i-1]] ?(即這兩個值是否相等)

解釋:第 i 個位置的前乙個位置的值(即 p[i-1],記作 m)與以 m 的 next 值(即 next[i-1])為下標的值(即 p[next[i-1]],記作 n)是否相等,(看的懵懵的也沒關係,後面會有例子)

(2)第二種求法:根據最大公共元素長度求

首先附上講解的博文位址,裡面有詳細講解 

1)算出每乙個字母字首字尾的最大公共元素長度 

2)最大公共元素長度整體向後移動乙個長度,最前面的元素值填 -1,即為 next 陣列的第一版本 

3)(如果你需要的 next 陣列第乙個值為 -1,這步就可以省略了)next 陣列的每乙個值分別+1,即求得 next 陣列。

三、例項

字串 p =「ababaaababaa」

求解: 

(1)對應上面第一種求法

1)初始化pa

baba

aaba

baa下標

1234

5678

9101112

next01

2)求下標為 3 的字元的 next 值 

p[3-1] = p[2] = 『b』; 

next[3-1] = next[2] = 1 ; 

p[next[3-1]] = p[1] = 『a』; 

p[3-1] != p[next[3-1]] ,但是此時已經回溯到了第乙個元素, 

∴ 直接p[3] = 1 ;pa

baba

aaba

baa下標

1234

5678

9101112

next01

13)求下標為 4 的字元的 next 值 

p[4-1] = p[3] = 『a』; 

next[4-1] = next[3] = 1 ; 

p[next[4-1]] = p[1] = 『a』; 

p[4-1] == p[next[4-1]] ; 

∴ next[4] = next[4-1] + 1 = 2 ;pa

baba

aaba

baa下標

1234

5678

9101112

next01

124)求下標為 5 的字元的 next 值 

p[5-1] = p[4] = 『b』; 

next[5-1] = next[4] = 2 ; 

p[next[5-1]] = p[2] = 『b』; 

p[5-1] == p[next[5-1]] ; 

∴ next[5] = next[5-1] + 1 = 3 ;pa

baba

aaba

baa下標

1234

5678

9101112

next01

1235)求下標為 6 的字元的 next 值 

推導過程同上 => next[6] = next[6-1] + 1 = 4 ;pa

baba

aaba

baa下標

1234

5678

9101112

next01

1234

6)求下標為 7 的字元的 next 值 

p[7-1] = p[6] = 『a』; 

next[7-1] = next[6] = 4 ; 

p[next[7-1]] = p[4] = 『b』; 

p[7-1] != p[next[7-1]] && 此時還未回到第乙個,繼續 

next[next[7-1]] = next[4] = 2 ; 

p[next[next[7-1]]] = p[2] = 『b』;番外(1) 

p[7-1] != p[next[next[7-1]]] && 但是此時還未回到第乙個,繼續 

next[next[next[7-1]]] = next[2] = 1 ; 

p[next[next[next[7-1]]]] = p[1] = 『a』 ; 

p[7-1] == p[next[next[next[7-1]]]] ; 

∴ next[7-1] = next[next[next[7-1]]] + 1 = next[2] + 1 = 2 ;pa

baba

aaba

baa下標

1234

5678

9101112

next01

1234

27)求下標為 8 的字元的 next 值 

p[8-1] = p[7] = 『a』; 

next[8-1] = next[7] = 2 ; 

p[next[8-1]] = p[2] = 『b』; 

p[8-1] != p[next[8-1]] ,但是還沒回到第乙個元素,繼續 

next[next[8-1]] = next[2] = 1 ; 

p[next[next[8-1]]] = p[1] = 『a』; 

p[8-1] == p[next[next[8-1]]]; 

∴ next[8] = next[next[8-1]] + 1 = 2pa

baba

aaba

baa下標

1234

5678

9101112

next01

1234

228)求下標為 9 的字元的 next 值 

推導過程同4) => next[9] = next[9-1] + 1 = 3 ;pa

baba

aaba

baa下標

1234

5678

9101112

next01

1234

2239)求下標為 10 的字元的 next 值 

推導過程同4) => next[10] = next[10-1] + 1 = 4 ;pa

baba

aaba

baa下標

1234

5678

9101112

next01

1234

2234

10)求下標為 11 的字元的 next 值 

推導過程同4) => next[11] = next[11-1] + 1 = 5 ;pa

baba

aaba

baa下標

1234

5678

9101112

next01

1234

2234

511)求下標為 12 的字元的 next 值 

推導過程同4) => next[12] = next[12-1] + 1 = 6 ;pa

baba

aaba

baa下標

1234

5678

9101112

next01

1234

2234

56(2)對應上面第二種求法

1)算出每乙個字母字首字尾的最大公共子串長度(下一步會把最後一位移走,所以最後一位可以不算)番外(2)pa

baba

aaba

baa前字尾最大公共子串長度00

1231

1234

52)最大公共子串長度整體向後移動乙個長度,最前面的元素值填 -1,即為 next 陣列的第一版本pa

baba

aaba

baanext 陣列第一版-10

0123

1123

453)(如果你需要的 next 陣列第乙個值為 -1,這步就可以省略了)next 陣列的每乙個值分別+1,即求得 next 陣列。pa

baba

aaba

baanext 陣列第二版01

1234

2234

56

next陣列求法和KMP演算法

首先介紹什麼是next陣列 定義 next i 表示是子串s 0 i 的最長相等前字尾的字首的最後一位下標。認真理解不難 下圖給出了next陣列的定義計算 其中下框第一行是字首,下框第二行是字尾 注意字首和字尾可以部分重疊但是不能使是s 0 i 本身 很好理解這是必然因為字首和字尾都是本身,比較毫無...

KMP演算法中Next陣列的求法

例如 序列號 1 2 3 4 5 6 7 8 模式串 a b a a b c a c next值 0 1 1 2 2 3 1 2 next陣列的求解方法是 第一位的next值為0,第二位的next值為1,後面求解每一位的next值時,根據前一位進行比較。首先將前一位與其next值對應的內容進行比較,...

KMP中幾種Next陣列的求法

今天覆習到 kmp 演算法時候發現考研教材上的 next 陣列和我之前學的不一樣,所以特地拎出來比對一下,順便總結。因為我之前掌握的 kmp 是李煜東的 演算法競賽高階指南 上介紹的,而考研教材似乎更多用的是嚴蔚敏的 資料結構 c語言版 所以就對這兩種實現方式做整理。競賽版設 p i j 為模式串 ...