1. 程式人生 > >演算法:KMP 演算法實現及詳解

演算法:KMP 演算法實現及詳解

未完待續 、、、

求下標 K 所對應的 next 陣列對應值的具體方法為:

  1. 觀察下標 K -1 對應字串的值,令 X 為下標 K -1 對應的 next 陣列的值
  2. 若 X 為-1,則下標 K對應的 next 陣列值為 0,否則進入步驟3
  3. 觀察下標為 X 的字串的值是否與下標 K對應字串的值相等,若相等則下標 K對應的 next 陣列值為 X+1,否則進入步驟4
  4. 令X = next[X] ,返回步驟3

對字串 “abaababaa” 共 9 個字元求 next 陣列,下表為結果:

字元陣列 a b a a b a b a a
下標 0 1 2 3 4 5 6 7 8
next陣列 -1 0 0 1 1 2 3 2 3

分解求解步驟

1、初始化,如下表

2、求解下標為1對應的next陣列,觀察 next[0] 的值 X = -1,則 next[1] = 0,如下表:

3、求解下標為2對應的next陣列,觀察 next[1] 的值 X = 0,觀察下標 1 對應的字元 b ,下標為 X(0) 對應的字元為 a ,兩者不一致,則令 X=next [X(0)] 即 X = -1,即 next[2] = 0,如下表:

4、求解下標為3對應的next陣列,觀察 next[2]

的值 X = 0,觀察下標 2 對應的字元 a ,下標為 X(0) 對應的字元為 a ,兩者一致,則 next [3] = next[2] + 1,即 next[3] = 1,如下表:

5、求解下標為4對應的next陣列,觀察 next[3] 的值 X = 1,觀察下標 3 對應的字元 a ,下標為 X(1) 對應的字元為 b ,兩者不一致,則令 X=next [X(1)] 即 X = 0,下標為 X(0) 對應的字元為 a,兩者一致,則 next [4] = next[1] + 1,即 next[4] = 1,如下表:

6、求解下標為5對應的next陣列,觀察 next[4] 的值 X = 1,觀察下標 4 對應的字元 b ,下標為 X(1) 對應的字元為 b ,兩者一致

,則 next [5] = next[4] + 1,即 next[5] = 2,如下表:

7、求解下標為6對應的next陣列,觀察 next[5] 的值 X = 2,觀察下標 5 對應的字元 a ,下標為 X(2) 對應的字元為 a ,兩者一致,則 next [6] = next[5] + 1,即 next[6] = 3,如下表:

8、求解下標為7對應的next陣列,觀察 next[6] 的值 X = 3,觀察下標 6 對應的字元 b ,下標為 X 對應的字元為 a ,兩者不一致,則令 X=next [X(3)] 即 X = 1,下標為 X(1) 對應的字元為 b,兩者一致,則 next [7] = next[3] + 1,即 next[7] = 2,如下表:

9、求解下標為8對應的next陣列,觀察 next[7] 的值 X = 2,觀察下標 7 對應的字元 a ,下標為 X 對應的字元為 a ,兩者一致

則 next [8] = next[7] + 1,即 next[8] = 3,如下表:

觀察法求出 next 陣列:

  • 求下標 K 的 next 陣列的值,即從字串首往後到下標 K - 1 觀察得出字首,從下標 K -1 往前到串首觀察得出字尾
  • 觀察字首和字尾一致時的長度最大值,該值即為下標 K對應的next 陣列的值

字首:整個字串"abaababaa"的字首為 a | ab | aba | abaa | abaab | abaaba | abaabab | abaababa

字尾:整個字串"abaababaa"的字首為 a | aa | baa | abaa | babaa | ababaa | aababaa | baababaa

例子1:求解下標為 4 的 next 陣列的值,即觀察 abaa 的字首 [ a , ab , aba ],字尾 [ a , aa , baa ],

字首字尾一致的只有 a ,長度為 1,則 next [ 4 ] = 1;

例子2:求解下標為 6 的 next 陣列的值,即觀察 abaaba 的字首 [ a,ab,aba,abaa,abaab ],

字尾 [ a,ba,aba,aaba,baaba],前後綴一致的有 a,aba,長度分別為 1 和 3,則取最大值 next [ 6 ] = 3;

Q:為什麼對 next 陣列的前兩位初始化為 -1?

在進行KMP匹配時,若下標標誌 i 用於被匹配字串,如“baab”,下標標誌 j 用於匹配字串“ab

b a a b
下標 0 1 2 3
i
a b
下標 0 1
j
next -1 0

當 i=0,j=0時,不匹配,此時需要將 i 指向下一位,且將 j 指向下標 0,

進行 j = next[j] 操作,即 j = -1,顯然,無該下標,則 i 與 j 同時進行++操作,即可將 i 指向下一位 1,且將 j 指向下標 0,

當 i = 1,j = 0時,匹配, i 與 j 同時進行++操作,

當 i = 2,j = 1時,不匹配,則 j = next[j],即 j = 0,

當 i = 2,j = 0時,匹配, i 與 j 同時進行++操作,

當 i = 3,j = 1時,匹配, i 與 j 同時進行++操作,到字串末尾,匹配完成;

PS:不需要一定將next的第一位一定初始化為-1,如果完全理解演算法之後也可根據自己的演算法定義將其定為0