KMP 算法中 next 数组手工求解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KMP 算法中 next 数组手工求解相关的知识,希望对你有一定的参考价值。
参考技术AKMP算法是一种改进的字符串匹配算法,如果不研究编码的话,手工实现还是比较简单,小型字符串甚至不需要你去求 next 数组就能看出来怎么移动。但是会有一些题目让你求解 next 数组,这里就以一个题目讲一下手工求解的过程。
例:求串 ‘ababaaababaa’ 的 next 数组
观察第一个元素,它没有前缀和后缀(串本身不能作为前缀或后缀),所以记录数据为0(这个数字表示当存在前缀和后缀相同的情况下,所能包含的最大的元素)
观察前两个元素,前缀为a,后缀为b,不相同,即没有相同的前缀和后缀,所以同样记录数据为0
观察前三个元素,存在前后缀相同的情况,为a,记录数据为1
观察前四个元素,同样存在前缀后缀相同的情况,为ab,记录数据为2
观察第五个元素,相同的前后缀为aba( aba ba、ab aba ),记录数据为3
同理观察余下的(用加粗表示前缀、下划线表示后缀)
a baba_a_ 1
a babaa_a_ 1
ab abaa_ab_ 2
aba baa_aba_ 3
abab aa_abab_ 4
ababa a_ababa_ 5
ababaa ababaa 6
最后我们得到一组数值:0 0 1 2 3 1 1 2 3 4 5 6
在这组数开头添加 -1,并删去最后一个数值,数组变为: -1 0 0 1 2 3 1 1 2 3 1 1 2 3 4 5
所有值+1,变为:0 1 1 2 3 4 2 2 3 4 2 2 3 4 5 6,这就是我们需要的 next 数组
需要注意的是,不同的题目next[0]可能为-1,所以 -1 0 0 1 2 3 1 1 2 3 1 1 2 3 4 5 同样有可能作为 next 数组,但是这两种一定不会同时出现。
题目图片:
KMP算法模式匹配——手工求解next和nextval数组值
本文需要了解KMP算法基本流程和相关概念,如有问题,请先进行基础学习:链接: 天勤-KMP算法易懂版
求解next数组值
给定模式串:“ababaaab”,求解其next数组值。
例子里面的ababaaab,我们定义一个 i 为模式串的下标(从1开始),我们把 i 所指字符之前的串记为F(不包括i所指的字符),手推如下:
- 当 i = 1 时,此时指向a,发生不匹配,此时属于模式串的第一个字符与主串对应位置不匹配,应从主串的下一位置和模式串的第一个字符继续比较。那么此时,我们也将 next[1] 赋值为 0 来表示这种情况。
- 当 i = 2 时,此时指向b,发生不匹配,可知F为"a",此时属于不存在前后重合的部分,应该从主串中发生不匹配的字符与模式串第一个字符开始比较。我们可以把这种情况的最长相等前后缀的长度看为0,那么next[2]赋值为1。
- 当 i = 3 时,此时指向a,发生不匹配,此时可以知道F是"ab",与2中情况一样,则next[3]为1。
- 当 i = 4 时,此时指向b,发生不匹配,此时F为"aba",那么最长相等前后缀就为"a",长度为1,所以此时next[4]为2。
- 当 i = 5 时,此时指向a,发生不匹配,此时F为"abab",则最长相等前后缀为"ab",长度为2,故next[5]为3。
- 当 i = 6 时,此时指向a,发生不匹配,此时F为"ababa",最长相等前后缀为"aba",长度为3,则next[6]为4。
- 当 i = 7 时,此时指向a,发生不匹配,此时F为"ababaa",最长相等前后缀是"a",长度为1,则next[7]为2。
- 当 i = 8 时,此时指向b,发生不匹配,此时F为"ababaaa",最长相等前后缀是"a",长度为1,则next[8]为2。
综上,可以得出next数组值为 0 1 1 2 3 4 2 2
求解nextval数组值
给定模式串:“ababaaab”,求解其nextval数组值。
例子里面的ababaaab,我们定义一个 j 为模式串的下标(从1开始),设next数组里面的值为pj(j为下标)
一般步骤(j,k均为下标):
1.当 j 等于1时,nextval[j]赋值为0,作为特殊标记。
2.当pj不等于pk时(k等于next[j]),nextval[j]赋值为k。
3.当pj等于pk时(k等于next[j]),nextval[j]赋值为nextval[k]。
手推如下:
n
e
x
t
v
a
l
[
1
]
=
0
,
特殊标记
nextval[1] = 0 ,特殊标记
nextval[1]=0,特殊标记
p
2
为
b
,
p
n
e
x
t
[
2
]
为
a
,两者不相等,
n
e
x
t
v
a
l
[
2
]
=
n
e
x
t
[
2
]
=
1
;
p2为b,p_next\\left[ 2\\right] 为a,两者不相等,nextval[2]=next[2]=1;
p2为b,pnext[2]为a,两者不相等,nextval[2]=next[2]=1;
p
3
为
a
,
p
n
e
x
t
[
3
]
为
a
,两者相等,
n
e
x
t
v
a
l
[
3
]
=
n
e
x
t
v
a
l
[
n
e
x
t
[
3
]
]
=
0
;
p3为a,p_next\\left[ 3\\right] 为a,两者相等,nextval[3]=nextval[next[3]]=0;
p3为a,pnext[3]为a,两者相等,nextval[3]=nextval[next[3]]=0;
p
4
为
b
,
p
n
e
x
t
[
4
]
为
b
,两者相等,
n
e
x
t
v
a
l
[
4
]
=
n
e
x
t
v
a
l
[
n
e
x
t
[
4
]
]
=
1
;
p4为b,p_next\\left[ 4\\right] 为b,两者相等,nextval[4]=nextval[next[4]]=1;
p4为b,pnext[4]为b,两者相等,nextval[4]=nextval[next[4]]=1;
p
5
为
a
,
p
n
e
x
t
[
5
]
为
a
,两者相等,
n
e
x
t
v
a
l
[
5
]
=
n
e
x
t
v
a
l
[
n
e
x
t
[
5
]
]
=
0
;
p5为a,p_next\\left[ 5\\right] 为a,两者相等,nextval[5]=nextval[next[5]]=0;
p5为a,pnext[5]为a,两者相等,nextval[5]=nextval[next[5]]=0;
p
6
为
a
,
p
n
e
x
t
[
6
]
为
b
,两者不相等,
n
e
x
t
v
a
l
[
6
]
=
n
e
x
t
[
6
]
=
4
;
p6为a,p_next\\left[ 6\\right] 为b,两者不相等,nextval[6]=next[6]=4;
p6为a,pnext[6]为b,两者不相等,nextval[6]=next[6]=4;
p
7
为
a
,
p
n
e
x
t
[
7
]
为
b
,两者不相等,
n
e
x
t
v
a
l
[
7
]
=
n
e
x
t
[
7
]
=
2
;
p7为a,p_next\\left[ 7\\right] 为b,两者不相等,nextval[7]=next[7]=2;
p7为a,pnext[7]为b,两者不相等,nextval[7]=next[7]=2;
p
8
为
b
,
p
n
e
x
t
[
8
]
为
b
,两者相等,
n
e
x
t
v
a
l
[
8
]
=
n
e
x
t
v
a
l
[
n
e
x
t
[
8
]
]
=
1
;
p8为b,p_next\\left[ 8\\right] 为b,两者相等,nextval[8]=nextval[next[8]]=1;
p8为b,pnext[8]为b,两者相等,nextval[8]=nextval[next[8]]=1;
综上,nextval数组值为0 1 0 1 0 4 2 1
以上是关于KMP 算法中 next 数组手工求解的主要内容,如果未能解决你的问题,请参考以下文章