c语言next数组,串——求解next数组和nextval数组

一. 求解next

next数组的求解方法:首先第一位的next值直接给0,第二位的next值直接给1,后面求解每一位的next值时,都要前一位进行比较。首先将前一位与其next值的对应位进行比较,若相等,则该位的next值就是前一位的next值加上1;若不等,继续重复这个过程,直到找到相等某一位,将其next值加1即可,如果找到第一位都没有找到,那么该位的next值即为1。

故事助记:「检查作业」—— 这次是几分呢?

手里拿个小本,看左边的题目的结果,根据这个结果给出的位置找答案,哦一样的,在这个结果基础上加1分;哦不一样啊,以当前这个结果作为新结果,以新结果给出的位置继续找,重复进行,如果找到了,就在新结果基础上加1分;如果找不到,那就勉强给1分。

举例:

21e5816baf9a

next数组求解示例

求解步骤:

1.前两位必为0,1。

2.计算第三位的时候,看第二位b的next值,为1,则把b和1对应的a进行比较,不同,则第三位a的next的值为1,因为一直比到最前一位,都没有发生比较相同的现象。

3.计算第四位的时候,看第三位a的next值,为1,则把a和1对应的a进行比较,相同,则第四位a的next的值为第三位a的next值加上1,为2。因为是在第三位实现了其next值对应的值与第三位的值相同。

4.计算第五位的时候,看第四位a的next值,为2,则把a和2对应的b进行比较,不同,则再将b对应的next值1对应的a与第四位的a进行比较,相同,则第五位的next值为第二位b的next值加上1,为2。因为是在第二位实现了其next值对应的值与第四位的值相同。

5.计算第六位的时候,看第五位b的next值,为2,则把b和2对应的b进行比较,相同,则第六位c的next值为第五位b的next值加上1,为3,因为是在第五位实现了其next值对应的值与第五位相同。

6.计算第七位的时候,看第六位c的next值,为3,则把c和3对应的a进行比较,不同,则再把第3位a的next值1对应的a与第六位c比较,仍然不同,则第七位的next值为1。

7.计算第八位的时候,看第七位a的next值,为1,则把a和1对应的a进行比较,相同,则第八位c的next值为第七位a的next值加上1,为2,因为是在第七位和实现了其next值对应的值与第七位相同。

另解(不想看可跳过):

求next数组:

先求模式串S 每一个字符前面的那个字符串的最大公共前后缀长度,将这一系列长度存成一个数组,求出来的每个长度其实就是和模式串每一个对应位置上做比较的下标

例如:模式串是ABACABC,其最长公共前后缀长度数组为:我们将最长公共前后缀长度记作LCPSF,现在从模式串第一个字符A开始,A的前面字符串为null,所以A之前的子串的LCPSF是0;来到B,B的前面字符串是A,A是单独的字符不存在公共前后缀,所以长度也是0;来到A,A前面的子串是AB,LCPSF为0;来到C,C前面的子串是ABA,LCPSF为1;来到A,A前面的子串是ABAC,LCPSF为0;来到B,B之前子串为ABACA,LCPSF为1;来到C,C前面子串为ABACAB,LCPSF为2;到此这个最长公共前后缀数组就出来了[0,0,0,1,0,1,2]将这个数组从第二个值开始每个值加1后,得到[0,1,1,2,1,2,3] 就是将要和子串对应位置比较的下标,即为next数组。

二、求解nextval数组

掌握了上面求next数组的方法后,我们可以迅速求得模式串ABACABC的next数组为[0,1,1,2,1,2,3],现在继续求模式串ABACABC的next-val数组:

求解nextval数组是基于next数组的,模式串每一个位置的字符和其next数组值给出的下标的对应位置的数作比较,相等就取next-val中对应的next数组值作为当前位置字符的next-val值,不等就直接取当前位置字符的next数组的值作为next-val的值。

故事助记:(nextval数组第一位始终是0,从第二位开始)妈妈都会告诉小朋友不要相信陌生人,确定nextval数组的问题就可以抽象为要不要拿别人东西吃的问题,每个小朋友心里都有自己想吃的东西(当前位置数组项),并且每位小朋友手里都有一个线索(next数组项对应每位小朋友手里的线索),当别人给自己东西吃的,就拿自己线索对应的别人的吃的东西做比较,如果线索对应的东西不是自己爱吃的,那就选择吃自己的东西(保留自己的线索),否则就吃别人的东西(把别人的线索拿过来)。

求解步骤:

next-val数组第一个数直接为0。

next-val第二数:模式串第二个字符为B,对应的下标数组第二个数是1,那就是将模式串的第1个字符和B相比较,A!=B,所以直接将下标数组第二个数1作为next-val数组第二个数的值

第三个数:模式串第三个字符为A,对应下标数组第三个数为1,取其作为下标,找到模式串第1个字符为A,A=A,那取next-val的第一个数做为next-val第三个数的值,也就是0

举例:

位置

1

2

3

4

5

6

7

模式串

A

B

A

C

A

B

C

next数组

0

1

1

2

1

2

3

nextval数组

0

1

0

2

0

1

3

注意,这里所有序号,第一个位置都是1开始

三、next 和 nextval 比较

next数组的缺陷举例如下:

比如主串是"aabXXXXXXXXXXXXXX",模式串"aac"

通过计算 "aac" 的next数组为012,当模式串在字符c上失配时,会跳到第2个字符,然后再和主串当前失配的字符重新比较,即此处用模式串的第二个a和主串的b比较,即 "aabXXXXXXXXXXXXXX"vs"aac",显然a也不等于b。然后会跳到1接着比,直到匹配成功或者匹配失败主串后移一位。

而"aac"的nextval数组为002 当在c失配时会跳到2,若还失配就直接跳到0,比next数组少比较了1次。

在如果模式串很长的话,那可以省去很多比较,因此使用nextval数组比next数组高效。

四、问题思考:

在模式匹配的KMP算法中,求模式的next数组值(也称为KMP算法中失败函数)定义如下:

21e5816baf9a

next数组的定义

(1)当j=1时,为什么要取next[1]=0?

答:当模式串第一个字符与主串中某字符不匹配时,主串指针应移至下一字符,再和模式串第一个字符比较。(next[1]=0 表示模式串中已没有字符可与主串中当前字符 s[i] 比较)

(2)为什么要取 max{k},k最大是多少?

答:当主串中第 i 个字符与模式串中第 j 个字符不匹配时,若主串 i 不回溯,则假定模式串中第 k 个字符与主串中第 i 个字符比较,k 值应满足条件 1

(3)其它情况是什么?为什么取 next[j] = 1?

答:以上两种情况的不匹配,主串指针不回溯,在最坏的情况下,模式串从第 1 个字符开始与主串第 i 个字符比较,以便不丢失可能的匹配。

  • 4
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值