求next数组:
步骤:
初始指针j指向前缀末尾,指针i指向后缀末尾,这里i也代表着当前遍历的位置
开始移动指针i,找到与前缀第一个字符相同的字符作为后缀的起始位置(如果不相同,j不动,i一直向后移动),找到第一个相同的字符后,对于已经遍历过的字符所组成的字符串来说,i此时指向的该字符串的末尾,如下图所示,此时已经遍历过的字符串为a, ab, 正在遍历的是 aba 而 i 指向 a(这就是为什么说i指向后缀末尾),这个遍历顺序一定是a, ab, aba, abac, abaca, .... , abacacab。
接着 i,j 同时向后移动,在这个过程中如果一直有string[i] == string[j],我们直接1加上前面已经记录的最长前后缀长度就行了。别忘了记录 next[i] = j;
如果string[j] != string[i],为了更清楚的描述,我们直接假设来到如下图所示的位置。此时我们应该回退指针 i,j 。指针 j 直接回到原点,然后回退指针 i 一直找到string[i] == string[j],然后又开始向之前那样正常遍历。
但这样一来就需要回退遍历指针 i ,而且就没有利用好前面已经得到的信息,这里其实就和KMP算法要解决的问题是一样的,KMP就是要解决指针回退的问题,如果下图所示。
那么我们可以再次使用KMP算法的思想,如果加入 b 后最长公共前后缀为 abac, 那么整个字符串中至少存在两个相同的字符串 abac,再次运用kmp算法的思想,在 abacabab 中去找 abac ,这也就是代码中回退指针 j,使 j = next[j - 1].
这里原字符串最后面的 ac 是为了理解而加上去的!!!