FZU - 1901 ——Period II (所有循环节)

For each prefix with length P of a given string S,if

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
Input contains multiple cases.

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.

Output
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
stostootssto
Sample 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);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_41380961/article/details/80278317