For each prefix of a given string S with N characters (each character has an ASCII code between 97 and 126, inclusive), we want to know whether the prefix is a periodic string. That is, for each i (2 <= i <= N) we want to know the largest K > 1 (if there is one) such that the prefix of S with length i can be written as A
K , that is A concatenated K times, for some string A. Of course, we also want to know the period K.
3 aaa 12 aabaabaabaab 0
Test case #1 2 2 3 3 Test case #2 2 2 6 2 9 3 12 4
题解:
给你一个串,从第二位起到最后的每一个i,问你从串的第一位到第i位是否能形成一个循环节,如果可以,输出当前的i和可以找到最多循环节的循环的次数
思路:
直接KMP搞一搞就好了,i-next[i]就相当于当前最小的循环节长度,设为t,当t%i==0&&t/i>1的时候即就是能形成循环的时候,因为KMP求出的就是最多的循环次数,输出t/i就是了
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<math.h>
#include<string>
#include<stdio.h>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<deque>
using namespace std;
#define lson k*2
#define rson k*2+1
#define M (t[k].l+t[k].r)/2
#define INF 1008611111
#define ll long long
#define eps 1e-15
int Next[1000005];
char T[1000005];
void init()
{
int i,j;
i=0,j=-1;
Next[0]=-1;
while(T[i])
{
if(j==-1||T[i]==T[j])
{
i++;
j++;
Next[i]=j;
}
else
j=Next[j];
}
}
int main()
{
int i,j,n,cas=1;
while(scanf("%d",&n)!=EOF&&n)
{
scanf("%s",T);
init();
printf("Test case #%d\n",cas);
cas++;
for(i=1;i<=n;i++)
{
int t=i-Next[i];
if(i%t==0&&i/t>1)
{
printf("%d %d\n",i,i/t);
}
}
printf("\n");
}
return 0;
}