The little cat is so famous, that many couples tramp over hill and dale to Byteland, and asked the little cat to give names to their newly-born babies. They seek the name, and at the same time seek the fame. In order to escape from such boring job, the innovative little cat works out an easy but fantastic algorithm:
Step1. Connect the father's name and the mother's name, to a new string S.
Step2. Find a proper prefix-suffix string of S (which is not only the prefix, but also the suffix of S).
Example: Father='ala', Mother='la', we have S = 'ala'+'la' = 'alala'. Potential prefix-suffix strings of S are {'a', 'ala', 'alala'}. Given the string S, could you help the little cat to write a program to calculate the length of possible prefix-suffix strings of S? (He might thank you by giving your baby a name:)
Input
The input contains a number of test cases. Each test case occupies a single line that contains the string S described above.
Restrictions: Only lowercase letters may appear in the input. 1 <= Length of S <= 400000.
Output
For each test case, output a single line with integer numbers in increasing order, denoting the possible length of the new baby's name.
Sample Input
ababcababababcabab
aaaaa
Sample Output
2 4 9 18
1 2 3 4 5
我们用上面那个字符串为例子来说明一下。
下标 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[i] -1 0 0 1 2 0 1 2 3 4 3 4 3 4 5 6 7 8 9
1)当i = len时,next[len] = next[18] = 9,说明整个字符串前9个字符和后9个字符相同,所以9是满足要求的。
2)next[9] = 4,说明在0-8中前4个字符和后4个字符相同。因为由1)得前9个字符和后9个字符相同,所以,S串的0-3等于5-8,而0-3又等于9-12,5-8又等于14-17,所以结果是0-3等于14-17,即4也是满足题意的。
3)next[4]=2,同2,我们可以得到2也是满足题意的。
4)next[2]=0,表明没有相同的前缀和后缀了,这时,就已经找到了这个S串的所有前缀和后缀。
5)结果就是2,4,9,18.
所以,我们可以推得这样的结论:凡是next[i]!=0的,都是模式串的前缀和后缀相同的字符数。
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
char s[400010];
int ne[400010];
int num[400010];
void getnext(char s[],int slen)
{
int i=0,j=-1;
ne[0]=-1;
while(i<slen)
{
if(j==-1||s[i]==s[j])
{
i++;
j++;
ne[i]=j;
}
else
j=ne[j];
}
// for(int k=0;k<i;k++) //判断next值
// printf("%d",ne[k]);
}
int main()
{
while(~scanf("%s",s))
{
int slen=strlen(s);
getnext(s,slen);
int t=ne[slen-1]; //t是用来放在s数组中作比较的所以要用slen-1,数组ne是从0开始的
int k=0;
while(t!=-1)
{
if(s[t]==s[slen-1])
{
++k;
num[k]=t+1; //让数组num从1开始存
}
t=ne[t];
}
for(int j=k;j>=1;j--)
{
printf("%d ",num[j]);
}
printf("%d\n",slen);
}
return 0;
}