题目大意 :给定一个字符串,求其相同前缀后缀的长度,由小到大输出所有情况
题目分析 :用到KMP算法中的next数组,本题时next数组的一种新用法,要深刻理解next数组的含义,由KMP算法的原理可知,通过遍历next[len], next[next[len]].....可以得到所有同时满足是原串的前缀和后缀的子串长度.
下标 : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
原串 : a b a b c a b a b a b a b c a b a b
next : -1 0 0 1 2 0 1 2 3 4 3 4 3 4 5 6 7 8 9
串长18肯定是一个解,到18失配,next[18] = 9第二个解为9, 到9失配,next[9] = 4第三个解为4,到4失配,next[4] = 2第四个解为2
到2失配next[2] = 0结束,所以解集是{18,9,4,2}然后再逆序输出,这样做的原因是到18失配了,next值为9,所以原串的前9个字符和后9个字符必然是相同的(ababcabab),那么我们只需要再看前9个字符组成的子串,next[9]=4,说明前9个字符的前4个和后4个是相同的(abab)又因为后9个字符和前9个字符是相同的,所有后9个字符的前4个和后4个是相同的(abab),因此我们可以推出前九个字符的前4个字符和后9个字符的后4个字符是相同的,即原串的前4个字符和后4个字符是相同的,2的情况一样,
#include <cstdio>
#include <cstring>
int const MAX = 400000 + 5;
char str[MAX];
int next[MAX];
int ans[MAX];
void next()
{
next[0] = -1;
int k = -1, j = 0;
while(str[j] != '\0')
{
if(k == -1 || str[j] == str[k])
{
k++;
j++;
next[j] = k;
}
else
k = next[k];
}
}
int main()
{
int count;
while(scanf("%s", str) != EOF)
{
count = 0;
next();
int temp = strlen(str);
while(temp != 0)
{
ans[count++] = temp;
temp = next[temp];
}
for(int i = count - 1; i >= 0; i--) //逆序输出
printf("%d ",ans[i]);
printf("\n");
}
}