next数组值的推导
next数组值只与模式串相关(子串是主串的子集)
令
n
e
x
t
[
j
]
=
k
next[j]=k
next[j]=k ,则
n
e
x
t
[
j
]
next[j]
next[j] 表明当模式串T中第
j
j
j 个字符与主串S中相应字符匹配失败时,模式串T的下标应该变为
k
k
k 值后再与主串S中的该字符进行比较
在前后缀字符中:
零个字符相等,k值为 1
一个字符相等,k值为 2
两个字符相等,k值为 3
n 个字符相等,k值为
n
+
1
n+1
n+1
1.模式串T=“abcdex”(无重复字符)
因为此模式串中没有重复的字符,所以匹配失败后,均需要回到模式串首位
k
=
1
k=1
k=1
j
j
j从 1 到
j
−
1
j-1
j−1
①当
j
=
1
j=1
j=1 时,next[1]=0(next函数定义)???
②当
j
=
2
j=2
j=2 时,
j
j
j 从 1 到 1,从1到1的串为
a
a
a,next[2]=1
③当
j
=
3
j=3
j=3 时,
j
j
j 从 1 到 2,从1到2的串为
a
b
ab
ab,next[3]=1
④当
j
=
4
j=4
j=4 时,
j
j
j 从 1 到 3,从1到3的串为
a
b
c
abc
abc,next[4]=1
⑤当
j
=
5
j=5
j=5 时,
j
j
j 从 1 到 4,从1到4的串为
a
b
c
d
abcd
abcd,next[5]=1
⑥当
j
=
6
j=6
j=6 时,
j
j
j 从 1 到 5,从1到5的串为
a
b
c
d
e
abcde
abcde,next[6]=1
2.模式串T=“abcabx”(有重复字符)
j
j
j从 1 到
j
−
1
j-1
j−1
①当
j
=
1
j=1
j=1 时,next[1]=0(next函数定义)???
②当
j
=
2
j=2
j=2 时,
j
j
j 从 1 到 1,从1到1的串为
a
a
a,next[2]=1
③当
j
=
3
j=3
j=3 时,
j
j
j 从 1 到 2,从1到2的串为
a
b
ab
ab,next[3]=1
④当
j
=
4
j=4
j=4 时,
j
j
j 从 1 到 3,从1到3的串为
a
b
c
abc
abc,next[4]=1
⑤当
j
=
5
j=5
j=5 时,
j
j
j 从 1 到 4,从1到4的串为
a
b
c
a
abca
abca,前缀字符为a,后缀字符为a,即有1个字符相等,即k=1+1=2,有next[5]=2
⑥当
j
=
6
j=6
j=6 时,
j
j
j 从 1 到 5,从1到4的串为
a
b
c
a
b
abcab
abcab,前缀字符为ab,后缀字符为ab,即有2个字符相等,k=2+1=3,next[6]=3
3.模式串T=“ababaaaba”(有重复字符)
j
j
j从 1 到
j
−
1
j-1
j−1
①当
j
=
1
j=1
j=1 时,next[1]=0(next函数定义)???
②当
j
=
2
j=2
j=2 时,
j
j
j 从 1 到 1,从1到1的串为
a
a
a,next[2]=1
③当
j
=
3
j=3
j=3 时,
j
j
j 从 1 到 2,从1到2的串为
a
b
ab
ab,next[3]=1
④当
j
=
4
j=4
j=4 时,
j
j
j 从 1 到 3,从1到3的串为
a
b
a
aba
aba,前缀字符为a,后缀字符为a,即有1个字符相等,k=1+1=2,next[4]=2
⑤当
j
=
5
j=5
j=5 时,
j
j
j 从 1 到 4,从1到4的串为
a
b
a
b
abab
abab,前缀字符为ab,后缀字符为ab,即有2个字符相等,k=2+1=3,next[5]=3
⑥当
j
=
6
j=6
j=6 时,
j
j
j 从 1 到 5,从1到5的串为
a
b
a
b
a
ababa
ababa,前缀字符为aba,后缀字符为aba,即有3个字符相等,k=3+1=4,next[6]=4
⑦当
j
=
7
j=7
j=7 时,
j
j
j 从 1 到 6,从1到6的串为
a
b
a
b
a
a
ababaa
ababaa,前缀字符为a,后缀字符为a,即有1个字符相等,k=1+1=2,next[7]=2
⑧当
j
=
8
j=8
j=8 时,
j
j
j 从 1 到 7,从1到7的串为
a
b
a
b
a
a
a
ababaaa
ababaaa,前缀字符为a,后缀字符为a,即有1个字符相等,k=1+1=2,next[8]=2
⑨当
j
=
9
j=9
j=9 时,
j
j
j从 1 到 8,从1到8的串为
a
b
a
b
a
a
a
b
ababaaab
ababaaab,前缀字符为ab,后缀字符为ab,即有2个字符相等,k=2+1=3,next[9]=3
4.模式串T=“aaaaaaaab”(有重复字符)
j
j
j从 1 到
j
−
1
j-1
j−1
①当
j
=
1
j=1
j=1 时,next[1]=0(next函数定义)???
②当
j
=
2
j=2
j=2 时,
j
j
j 从 1 到 1,从1到1的串为
a
a
a,next[2]=1
③当
j
=
3
j=3
j=3 时,
j
j
j 从 1 到 2,从1到2的串为
a
a
aa
aa,前缀字符为a,后缀字符为a,即有1个字符相等,k=1+1=2,next[3]=2
④当
j
=
4
j=4
j=4 时,
j
j
j 从 1 到 3,从1到3的串为
a
a
a
aaa
aaa,前缀字符为aa,后缀字符为aa,即有2个字符相等,k=2+1=3,next[4]=3
⑤当
j
=
5
j=5
j=5 时,
j
j
j 从 1 到 4,从1到4的串为
a
a
a
a
aaaa
aaaa,前缀字符为aaa,后缀字符为aaa,即有3个字符相等,k=3+1=4,next[5]=4
⑥当
j
=
6
j=6
j=6 时,
j
j
j 从 1 到 5,从1到5的串为
a
a
a
a
a
aaaaa
aaaaa,前缀字符为aaaa,后缀字符为aaaa,即有4个字符相等,k=4+1=5,next[6]=5
⑦当
j
=
7
j=7
j=7 时,
j
j
j 从 1 到 6,从1到6的串为
a
a
a
a
a
a
aaaaaa
aaaaaa,前缀字符为a,后缀字符为a,即有5个字符相等,k=5+1=6,next[7]=6
⑧当
j
=
8
j=8
j=8 时,
j
j
j 从 1 到 7,从1到7的串为
a
a
a
a
a
a
a
aaaaaaa
aaaaaaa,前缀字符为a,后缀字符为a,即有6个字符相等,k=6+1=7,next[8]=7
⑨当
j
=
9
j=9
j=9 时,
j
j
j从 1 到 8,从1到8的串为
a
a
a
a
a
a
a
aaaaaaa
aaaaaaa,前缀字符为ab,后缀字符为ab,即有7个字符相等,k=7+1=8,next[9]=8
假设模式串的第一位与主串匹配失败
next[1]:
T
[
1
]
T[1]
T[1] 前无字符,谈不上公共前后缀字符
next[1]=0:模式串下标由1“跳”到0
假设模式串的第二位与主串匹配失败
next[2]:下标为2的位置匹配失败后,模式串的下标应该跳到哪一个位置继续与主串当前位置进行比较
T
[
2
]
T[2]
T[2] 前仅有一个字母A,无公共前后缀字符,所以
j
=
0
+
1
=
1
j=0+1=1
j=0+1=1
next[2]=1:模式串第2位匹配失败后,接着用模式串下标为1的字符与主串当前位置进行比较
假设模式串的第三位与主串匹配失败
next[3]:下标为3的位置匹配失败后,模式串的下标应该跳到哪一个位置继续与主串当前位置进行比较
T
[
3
]
T[3]
T[3] 前仅有字母AB,无公共前后缀字符,所以
j
=
0
+
1
=
1
j=0+1=1
j=0+1=1
next[3]=1:模式串第3位匹配失败后,接着用模式串下标为1的字符与主串当前位置进行比较
假设模式串的第四位与主串匹配失败
next[4]:下标为4的位置匹配失败后,模式串的下标应该跳到哪一个位置继续与主串当前位置进行比较
T
[
4
]
T[4]
T[4] 前子串为“ABA”,有
1
1
1 对公共前后缀字符,最大公共前后缀长度为1,故
j
=
1
+
1
=
2
j=1+1=2
j=1+1=2
将模式串“移动”到后缀字符位置
next[4]=1+1=2:模式串第3位匹配失败后,接着用模式串下标为2的字符与主串当前位置进行比较
假设模式串的第五位与主串匹配失败
next[5]:下标为5的位置匹配失败后,模式串的下标应该跳到哪一个位置继续与主串当前位置进行比较
T
[
5
]
T[5]
T[5] 前有子串“ABAB”,有
2
2
2 对公共前后缀字符,最大公共前后缀字符长度为2,故
j
=
2
+
1
=
3
j=2+1=3
j=2+1=3
将模式串“移动”到后缀字符位置
next[5]=2+1=3:模式串第5位匹配失败后,接着用模式串下标为3的字符与主串当前位置进行比较
假设模式串的第六位与主串匹配失败
next[6]:下标为6的位置匹配失败后,模式串的下标应该跳到哪一个位置继续与主串当前位置进行比较
T
[
6
]
T[6]
T[6] 前子串为“ABABA”,有3对公共前后缀字符,最大公共前后缀字符长度为3,故
j
=
3
+
1
=
4
j=3+1=4
j=3+1=4
将模式串“移动”到后缀字符位置
next[6]=3+1=4:模式串第6位匹配失败后,接着用模式串下标为4的字符与主串当前位置进行比较
next数组代码
void get_next(String T, int next[]){ //数组next
int i=1,j=0;
next[1]=0;
while(i < T.length){
if(j == 0 || T.ch[i] == T.ch[j] ){ //前缀字符等于后缀字符
++i;
++j;
next[i]=j; //将模式串由前缀位置“移动”到后缀位置
}else
j = next[j]; //字符不同,j值回溯
}
}
代入本篇文章的一个示例来走一遍程序
程序开始
i
=
1
,
j
=
0
i=1,j=0
i=1,j=0,next[1]=0
进入while循环
第一次循环:
j
=
0
j=0
j=0,自增后
i
=
2
,
j
=
1
i=2,j=1
i=2,j=1,next[2]=1
第二次循环:
i
=
2
,
j
=
1
,
T
[
2
]
≠
T
[
1
]
i=2,j=1,T[2] \ne T[1]
i=2,j=1,T[2]=T[1],j=next[1]=0
第三次循环:
j
=
0
j=0
j=0,自增后
i
=
3
,
j
=
1
i=3,j=1
i=3,j=1,next[3]=1
第四次循环:
i
=
3
,
j
=
1
,
T
[
3
]
≠
T
[
1
]
i=3,j=1,T[3] \ne T[1]
i=3,j=1,T[3]=T[1],j=next[1]=0
第五次循环:
j
=
0
j=0
j=0,自增后
i
=
4
,
j
=
1
i=4,j=1
i=4,j=1,next[4]=1
第六次循环:
i
=
4
,
j
=
1
,
T
[
4
]
=
T
[
1
]
i=4,j=1,T[4]=T[1]
i=4,j=1,T[4]=T[1],自增后
i
=
5
,
j
=
2
i=5,j=2
i=5,j=2,next[5]=2
第七次循环:
i
=
5
,
j
=
2
i=5,j=2
i=5,j=2,自增后
i
=
6
,
j
=
3
i=6,j=3
i=6,j=3,next[6]=3