For each prefix with length P of a given string S,if
Input
S[i]=S[i+P] for i in [0..SIZE(S)-p-1],
then the prefix is a “period” of S. We want to all the periodic prefixs.
Input contains multiple cases.
Output
The first line contains an integer T representing the number of cases. Then following T cases.
Each test case contains a string S (1 <= SIZE(S) <= 1000000),represents the title.S consists of lowercase ,uppercase letter.
For each test case, first output one line containing "Case #x: y", where x is the case number (starting from 1) and y is the number of periodic prefixs.Then output the lengths of the periodic prefixs in ascending order.
Sample Input
4 ooo acmacmacmacmacma fzufzufzuf stostootsstoSample Output
Case #1: 3 1 2 3 Case #2: 6 3 6 9 12 15 16 Case #3: 4 3 6 9 10 Case #4: 2 9 12
题意:输出所有可能的循环节。
思路:对next数组的理解。
反思:一开始的想法是找出最小循环节len-next[len].然后用最小循环节来找所有可能的循环节。后来一直wa。用随机法打了一些表找到了一组能证明错误的数据ababaaaabab.用最小循环节来求答案是7,11,正确答案是7,9,11。
最小循环节不能代表所有循环节。
AC代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#define M 1000010
using namespace std;
int nextt[M],len;
char a[M];
void init_kmp()
{
int i=0,j=-1;
nextt[0]=-1;
len=strlen(a);
while(i<len)
{
if(j==-1||a[i]==a[j])
{
nextt[++i]=++j;
}
else
j=nextt[j];
}
}
queue<int>q;
int main()
{
int t,ph=1;
scanf("%d",&t);
while(t--)
{
scanf("%s",a);
init_kmp();
int j=len;
while(j>0)
{
j=nextt[j];
q.push(j);
}
printf("Case #%d: %d\n",ph++,q.size());
printf("%d",len-q.front());//输出格式
q.pop();
while(!q.empty())
{
printf(" %d",len-q.front());
q.pop();
}printf("\n");
}
}
错误思路代码(留下参考,不再犯):
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define M 1000010
using namespace std;
char a[M];
int nextt[M],len;
void KMP()
{
int i=0,j=-1;
nextt[0]=-1;
len=strlen(a);
while(i<len)
{
if(j==-1||a[i]==a[j])
{
nextt[++i]=++j;
}
else
j=nextt[j];
}
}
int main()
{
int n,ph=1;
scanf("%d",&n);
while(n--)
{
scanf("%s",a);
KMP();
int tt=len-nextt[len];
printf("Case #%d: %d\n",ph++,(len+tt-1)/tt);
int i=tt;
for(;i<len;i+=tt)
{
printf("%d ",i);
}
printf("%d \n",len);
}
}