这篇文章写得是真烂,我都看不太懂了,回头我抽空改改,不过下面的代码是正确的
* next[n]代表字符串前n个字符组成的子串的长度相同且相等的最长前后缀串的长度
* 就比如 "abab"中前缀(以首字符开头不包括尾字符的子串)有: "a"、"ab","aba"; 后缀(概念相反):"b","ab","bab"
* 那么"abab"中很明显长度相同且相等的最长前后缀串是 "ab", 那么 next[4] = 2
*
* 最简单求字符串的最长相等前后缀的方法: 从 index = len(str) - 1(先看看最长串是否一样)开始,
* 比较str[0]~str[index] 和 str[len - index] ~ str[len - 1], 如果两个字符串相等则直接退出返回index+1,否则index--,直到index小于0
*
* 虽然上述方法简单,但太低效了,如果在计算next[k]时我们能利用之前算的next[0]~next[k-1],就好了
* 推导: 如果 next[q] = k, 会有这个:(像两个板子尽量合在一起使重合部分一模一样但不能完全覆盖)
* str[0] ~ str[k-1] ~ str[q-1]
* str[0] ~ str~[len-k] ~ str[q-1]
*
* 即 str[0] ~ str[k-1] 和 str~[q-k] ~ str[q-1] 相等
* 1、 此时计算 next[q+1], 如果 str[k] = str[q], 那么 next[q+1] = next[q] + 1: 没毛病
*
* str[0] ~ str[k-1]str[k] ~ str[q-1]str[q]
* str[0] ~ str~[q-k] ~ str[q-1]str[q]
*
* 那你咋知道next[q+1]不能>K+1呢,确实,如果是一般的情况下,重合长度变长,有这个可能
* 假如存在 next[q + 1] = j > k + 1 :
* str[0] ~ str[j-2]str[j-1] ~ str[q]
* str[0] ~ str[q-j]~ str[q-1]str[q]
* 此时把上下两个str[q]都挡住,此时很明显: next[q] = j-1 > k, 所以不符, next[q+1] <= k+1
*
* 2、 如果 str[k] != str[q],那么只能在 str[0]~str[k-1]中尽量找某个长度为j + 1的前缀串str[0]~str[j]
* 使得其和 str[q-k+j]~str[q-1](即在str[q-k]~str[q-1]中长度相等的后缀串)相等,并满足str[j+1] = str[q],此时 next[q+1] = j + 1
*
* str[0]~str[j]str[j+1]~str[k-1]str[k] ~ str[q-1]str[q]
* str[0] ~ str~[q-k]~str[q-k+j]~str[q-1]str[q]
*
* 当然我们不需要一个个试j值,其实我们已经有了j的值的最佳候选,仔细看看,我们已经证明了str[0] ~str[k-1] = str[q-k]~str[q-1]
* 如果要找前者的前缀串与后者的后缀串最大相等长度,再者两者相等,那就不是找str[0] ~str[k-1]长度相同且相等的最长前后缀串的长度
* 这不就是next[k]的定义吗,此时 k < q,所以 next[k] 已知
* 所以我们只需要令 k = next[k], 此时 str[0]~str[k-1]和 str[q]之前的k个字符必然相等,如果此时 str[k] = str[q], 那么 next[q + 1] = k + 1, 否则继续上述步骤找内部的最长串,k=next[k],直到k = 1,此时若还不满足, next[q+1] = 0,没辙了
*
代码如下:
#include <cstring>
#include <iostream>
using namespace std;
//"abab",next[5],len = 4 --> next[5]{-1,0,0,1,2}
//next[0]=-1,next[n]代表前n个字符的最长相等前后串长度
void calculateNext(const char *str, int *next, int len) {
next[0] = -1; //递归结束位, k < 1不就是 k = next[k] <= -1
next[1] = 0;
int k = next[1]; //k是上一个next的结果
for (int i = 2; i <= len; ++i) {
while (str[k] != str[i - 1] && k > -1) {
k = next[k]; //回溯
}
if (k > -1 && str[k] == str[i - 1]) { //找到了
k++;
} else {
k = 0; //还没找到
}
next[i] = k;
}
}
int main() {
char str[] = "abab";
int len = strlen(str);
int next[len];
calculateNext(str,next,len);
for(int i = 0;i< len; i++)
cout << next[i] << ",";
return 0;
}