【数据结构】next数组、nextval数组

目录

next数组的求解方法:

nextval数组的求解方法:


next数组的求解方法:

1.第一位的next值为0

2.第二位的next值为1

后面求解每一位的next值时,根据前一位进行比较

从第三位开始,比较前一位元素和其next值对应的元素是否相等

相等,所求的next值就是前一位的next值+1

不相等,则向前继续寻找next值对应的元素与前一位进行比较,直到找到与前一位相同的元素;若找到,则找到的这个位置的next值+1,就是所求的next值;若直到第一个元素,都没有找到与前一位元素相同的,则所求next值为0

nextval数组的求解方法:

利用next数组求nextval数组

nextval[1]=0;

从第二位开始,依次判断该位置的next值对应的元素与该位置的元素是否相同

相同,该位置的nextval的值就是在该位置next值对应元素的nextval的值

不相同,该位置的nextval的值就是该位置的next值

模式串 `ababc` 的 **next数组** 和 **nextval数组** 的计算步骤如下:

### 1. 计算next数组:
- **规则**:对于位置 `j`,找到其前 `j-1` 个字符的最长相等前后缀长度,再加1。
- **过程**:
  - `next[1] = 0`(规定)。
  - `next[2] = 1`(规定)。
  - `j=3`:子串 `ab` 无公共前后缀,`next[3] = 0 + 1 = 1`。
  - `j=4`:子串 `aba` 的最长公共前后缀为 `a`(长度1),`next[4] = 1 + 1 = 2`。
  - `j=5`:子串 `abab` 的最长公共前后缀为 `ab`(长度2),`next[5] = 2 + 1 = 3`。
- **结果**:`next = [0, 1, 1, 2, 3]`

### 2. 计算nextval数组:
- **规则**:若 `p[j] == p[next[j]]`,则 `nextval[j] = nextval[next[j]]`;否则 `nextval[j] = next[j]`。
- **过程**:
  - `nextval[1] = 0`(规定)。
  - `j=2`:`p[2] = b`,`p[next[2]] = p[1] = a`,不等,故 `nextval[2] = next[2] = 1`。
  - `j=3`:`p[3] = a`,`p[next[3]] = p[1] = a`,相等,故 `nextval[3] = nextval[1] = 0`。
  - `j=4`:`p[4] = b`,`p[next[4]] = p[2] = b`,相等,故 `nextval[4] = nextval[2] = 1`。
  - `j=5`:`p[5] = c`,`p[next[5]] = p[3] = a`,不等,故 `nextval[5] = next[5] = 3`。
- **结果**:`nextval = [0, 1, 0, 1, 3]`

### 最终答案:
- **next数组**:`[0, 1, 1, 2, 3]`
- **nextval数组**:`[0, 1, 0, 1, 3]`

```plaintext
next数组:0 1 1 2 3
nextval数组:0 1 0 1 3
```

C语言中的KMP(Knuth-Morris-Pratt)算法用于在文本串中查找模式串的第一次出现位置,它是一种改进的字符串匹配算法,通过构建next数组避免了在每次比较失败后回溯大量字符。以下是KMP算法的基本步骤以及如何编写相关的函数: 首先,我们需要创建两个数组: 1. next数组存储的是模式串的前缀最长公共前后缀长度。 2. nextval数组是一个辅助数组,通常不用直接输出,主要用于计算next数组。 ```c #include <stdio.h> #include <string.h> // 计算next数组 void compute_next(char pattern[], int length, int next[]) { int j = -1; // 指针j初始值为-1 for (int i = 1; i < length; ++i) { while (j != -1 && pattern[i] != pattern[j + 1]) { j = next[j]; // 如果当前字符不等于前缀的下一个字符,更新j指针 } if (pattern[i] == pattern[j + 1]) { // 如果相等,说明找到了新的前后缀 ++j; } next[i] = j; // 当前字符的next值为j } } // 主函数示例 int main() { char input[100], pattern[100]; printf("请输入字符串:"); fgets(input, sizeof(input), stdin); input[strlen(input) - 1] = '\0'; // 去除换行符 printf("请输入模式:"); fgets(pattern, sizeof(pattern), stdin); pattern[strlen(pattern) - 1] = '\0'; int length_input = strlen(input); int length_pattern = strlen(pattern); int next[length_pattern]; // 初始化next数组 compute_next(pattern, length_pattern, next); // 输出next数组 printf("Next array for pattern '%s':\n", pattern); for (int i = 0; i < length_pattern; ++i) { printf("%d ", next[i]); } return 0; } ``` 运行此程序时,用户需要输入一个字符串作为主串和一个模式串,然后会打印出模式串的next数组。注意,在实际应用中,你可能还需要处理输入的边界情况和错误检查。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值