KMP算法中Next数组及改进后的nextval数组的求法

【Next数组求法】

  • 第一二位对应的next值分别为0和1
  • 后面每一位的next值求解:根据前一位进行比较

    • 将前一位与其next值对应的内容进行比较
      • 相等,则该位的next值就是前一位的next值加上1
      • 不等
        • 向前继续寻找next值对应的内容来与前一位进行比较,直到找到某个位上内容的next值对应的内容与前一位相等为止,则这个位对应的值加上1即为需求的next值
        • 如果找到第一位都没有找到与前一位相等的内容,那么需求的位上的next值即为1
  • 例子1:

这里写图片描述

  • 例子2:

这里写图片描述

【nextval数组求法】

  • 先求next值
  • 第a位字符与它的next值指向的第b位字符相等,则a的nextval值为第b位的nextval值,若不等,则,a位的nextval值为它自己的next值

例子:ababaaaba

这里写图片描述

<think>嗯,用户问的是严蔚敏版本数据结构书中KMP算法next数组的计算方法。首先,我需要回忆一下严蔚敏书中的具体定义。记得严蔚敏的教材里,字符串的下标通常是从1开始的,而不是从0开始。这可能和其他的教材比如李春葆的有区别,李春葆的可能从0开始,所以next数组的定义会有差异。用户可能已经看过不同的资料,产生了混淆,所以需要明确说明严蔚敏版本的特点。 首先,严蔚敏的next数组定义应该是:next[j]表示当模式串中第j个字符与主串不匹配时,需要将模式串右移到next[j]的位置,即用模式串的第next[j]个字符与主串当前字符继续比较。这里下标从1开始,所以next[1]的值是0,这是一个基准情况,因为如果第一个字符就不匹配,那只能将整个模式串右移一位,从主串的下一个字符开始比较。 接下来,我需要解释严蔚敏版本的next数组的计算步骤。根据引用中的内容,严蔚敏的定义是将模式串下标从1开始,所以next[1]=0,next[2]=1。但根据引用3中的代码示例,虽然李春葆的版本下标从0开始,但用户提供的代码在输出时调整了next数组的值,加1来符合严蔚敏的定义。这说明可能严蔚敏的next数组在实际代码中需要调整索引,或者不同的教材有不同的实现方式。 用户可能需要具体的步骤来手动计算next数组。例如,以模式串"ababaaababaa"为例,代码的输出经过调整后得到的是0 1 1 2 3 4 2 2 3 4 5 6。这里每个位置对应的next值需要根据模式串的前缀和后缀的最长公共长度来计算,然后加1(因为严蔚敏的next数组是从1开始的,而代码可能从0开始计算,所以需要加1)。 可能需要详细说明如何通过比较前缀和后缀来得到每个位置的next值。例如,对于位置j,next[j]的值等于前j-1个字符组成的子串的最长相等前后缀长度加1。例如,当j=3时,子串是"ab",没有相等的前后缀,所以长度为0,next[3]=0+1=1。而当j=4时,子串是"aba",最长相等前后缀是"a",长度1,所以next[4]=1+1=2。 另外,引用2提到nextval数组是为了改进next数组在某些情况下的缺陷,但用户的问题主要集中在next数组的计算方法上,所以可能暂时不需要深入讨论nextval,但可以作为相关的问题提出。 需要注意的是,用户提供的代码示例中,虽然模式串下标从0开始,但通过输出时加1来适配严蔚敏的定义,因此需要解释清楚这一点。例如,代码中的ne数组初始化为-1,然后通过循环计算,最后输出时每个值加1,这样得到的结果符合严蔚敏的下标从1开始的next数组。 总结回答的结构应该包括:严蔚敏版本的特点(下标从1开始)、next数组的定义、计算步骤、实例说明,以及代码示例的解释。同时,根据用户的问题,可能需要比较不同教材的差异,避免混淆。</think>### 严蔚敏《数据结构》KMP算法next数组计算方法 #### 一、严蔚敏版本特点 1. **模式串下标从1开始**:字符位置编号为$1,2,...,n$,而非编程语言中的0起始下标[^3] 2. **定义基准**:$next[1] = 0$,当第一个字符失配时,主串指针后移一位,模式串从头开始匹配 3. **递推公式**:$next[j] = \begin{cases} 0 & j=1 \\ max\{k \mid 1 \le k < j \ 且\ p_1...p_{k-1} = p_{j-k+1}...p_{j-1}\} + 1 & 集合非空 \\ 1 & 其他情况 \end{cases}$ #### 二、手工计算步骤(以模式串$ababaaababaa$为例) 1. **初始化**:$next[1] = 0$ 2. **递推计算**: | 位置j | 前缀子串 | 最长相等前后缀长度 | next[j] | |-------|----------|--------------------|---------| | 2 | a | 0 | 1 | | 3 | ab | 0 | 1 | | 4 | aba | 1(a) | 2 | | 5 | abab | 2(ab) | 3 | | 6 | ababa | 3(aba) | 4 | | 7 | ababaa | 1(a) | 2 | | ... | ... | ... | ... | #### 三、代码实现特点[^3] ```cpp void getNext(string s) { int len = s.length(); int i = 0, j = -1; ne[0] = -1; // 兼容编程语言0起始下标 while(i < len) { if(j == -1 || s[i] == s[j]) { ne[++i] = ++j; // 实际存储的是公共前后缀长度 } else { j = ne[j]; } } } // 输出时需+1转换为严蔚敏定义值 ``` 代码中通过`ne[i]+1`输出,将编程实现的0起始下标转换为教材定义的1起始下标。例如输入$ababaaababaa$时,输出结果为$0\ 1\ 1\ 2\ 3\ 4\ 2\ 2\ 3\ 4\ 5\ 6$[^3] #### 四、与其他教材的差异 1. **李春葆版本**:模式串从0开始,$next[0]=-1$,计算时无需加1转换[^1] 2. **核心原理相同**:均基于最长相等前后缀长度确定滑动距离 3. **应用注意事项**:实现代码时需注意数组下标起始值的转换[^3]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值