演算法:KMP 演算法實現及詳解
未完待續 、、、
求下標 K 所對應的 next 陣列對應值的具體方法為:
- 觀察下標 K -1 對應字串的值,令 X 為下標 K -1 對應的 next 陣列的值
- 若 X 為-1,則下標 K對應的 next 陣列值為 0,否則進入步驟3
- 觀察下標為 X 的字串的值是否與下標 K對應字串的值相等,若相等則下標 K對應的 next 陣列值為 X+1,否則進入步驟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]
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 ,兩者一致
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