+ e8 x7 _* q9 Z. d0 N& ~提取加速匹配的信息+ W/ |! Q/ d0 z( D8 ^
上面说道 KMP 算法主要是通过消除主串指针的回溯来提高匹配的效率的,那么,它是则呢样来消除回溯的呢?就是因为它提取并运用了加速匹配的信息! 4 p9 j; m/ C0 M" z' Q6 f 这种信息就是对于每模式串 t 的每个元素 t j,都存在一个实数 k ,使得模式串 t 开头的 k 个字符(t 0 t 1…t k-1)依次与 t j 前面的 k(t j-k t j-k+1…t j-1,这里第一个字符 t j-k 最多从 t 1 开始,所以 k < j)个字符相同。如果这样的 k 有多个,则取最大的一个。模式串 t 中每个位置 j 的字符都有这种信息,采用 next 数组表示,即 next[ j ]=MAX{ k }。 [. E8 N8 j$ I j% n @( s Y2 I 加速信息,即数组 next 的提取是整个 KMP 算法中最核心的部分,弄懂了 next 的求解方法,也就弄懂了 KMP 算法的十之七八了,但是不巧的是这部分代码恰恰是最不容易弄懂的…… 5 i5 @& R4 ]+ i8 o , ]5 p7 L1 J. ~% R( [% S先上代码2 s- F% Q! g4 y9 E2 W
! J, E. n8 P2 b8 d' I! G; n9 H* c- V9 c& z- l
void Getnext(int next[],String t)- e |% }7 N% e) v
{9 ]' T6 ]0 g3 u* }* W
int j=0,k=-1;2 L- @$ X: \% M, [
next[0]=-1;" S$ A# B8 l; V0 Y" ?8 c4 n4 F
while(j<t.length-1) # G4 Q+ |3 N& ^% _' p {; d$ |9 J' J$ h/ M. M
if(k == -1 || t[j] == t[k]) , G8 z0 Y* V% L { - s9 n2 L: B9 d j++;k++; # }( Z! @( a( X( s4 K; E next[j] = k;3 E2 H6 j4 g4 F, \' `0 w
}8 f+ _8 K; ~ ?7 c8 Y) r2 g
else k = next[k];//此语句是这段代码最反人类的地方,如果你一下子就能看懂,那么请允许我称呼你一声大神! E% ^2 c) j F/ c5 U }. ^1 ]- _* i4 f" C3 ^: U" O1 k
}4 n. U$ O# ]# k) _+ C" \4 k. M
' B' `! ]; \! S% F" }0 I" Jok,下面咱们分三种情况来讲 next 的求解过程3 w1 O. C% O# `& {
6 Z6 q8 Z l% `' k4 }- I
- W0 @, H) I7 t0 T' |5 w
特殊情况 3 Z1 H+ K# r' ^. l: z1 g7 A当 j 的值为 0 或 1 的时候,它们的 k 值都为 0,即 next[0] = 0、next[1] =0。但是为了后面 k 值计算的方便,我们将 next[0] 的值设置成 -1。 0 s9 n& q l" D4 t9 ~5 m & h3 D0 `' z( B. N* u! D& ` * J& \" h3 I B' g8 q V当 t[j] == t[k] 的情况" { c- z4 A" r# G0 t! `
举个栗子 , F. ~8 w2 r( q# ] H" d6 M5 ?
" @6 h k' S s8 p+ \显然,当我们上边的算法得到的next数组应该是[ -1,0,0,1 ] 0 o0 N' u& l$ M. R; h9 r9 P+ @# _7 H% G. D
7 P2 a: I6 U1 f2 u
所以下一步我们应该是把j移动到第1个元素咯: , T1 ` r: Z( r { e