字符串的重复周期
Problem:1318
Time Limit:1000ms
Memory Limit:65535K
Description
给出字符串 S,求出串S的所有前缀中,是周期串的前缀的长度 Len 和他的最大重复周期 K
Input
多组样例。 对于每组样例 第一行输入串长 N (2<=N<=1e6) 第二行输入串 S 对于所有的S,长度和小于1e7
Output
对于S中是周期串的前缀 要求输出 K>1 的前缀的长度 Len 和最大重复周期 K 每一个长度和周期用一个空格分开。
Sample Input
3 aaa 12 aabaabaabaab
Sample Output
2 2 3 3 2 2 6 2 9 3 12 4
Hint
对于第一组样例 3 aaa 对于前缀 'a' Len = 1 ,K 最大为 1 不符合要求 对于前缀 'aa' Len = 2 ,K 最大为 2 周期串为 'a' 对于前缀 'aaa' Len = 3 ,K 最大为 3 周期串为 'a' 对于第二组样例 12 aabaabaabaab 对于前缀 'aa' Len = 2 ,K 最大为 2 周期串为 'a' 对于前缀 'aabaab' Len = 6 ,K 最大为 2 周期串为 'aab' 对于前缀 'aabaabaab' Len = 9 ,K 最大为 3 周期串为 'aab' 对于前缀 'aabaabaabaab' Len = 12 ,K 最大为 4 周期串为 'aab'
Source
DT2131
思路:
用KMP求出Next数组。然后从前往后搜,对于每一个i来说,周期都为i+1-next[i]。当周期能整除长度并且前缀长度不为1的时候,那么就输出长度和最大重复周期。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char t[1000005];
int ne[1000005];
char p[1000005];
void makenext(const char p[],int ne[],int len)
{
ne[0]=0;
for(int i=1,k=0;i<len;i++)
{
while(k>0&&p[i]!=p[k]) k=ne[k-1];
if(p[i]==p[k]) k++;
ne[i]=k;
}
}
int main()
{
int len;
while(~scanf("%d",&len))
{
scanf("%s",t);
makenext(t,ne,len);
for(int i=0;i<len;i++)
{
int zhouqi=i+1-ne[i];
if((i+1)%zhouqi==0&&ne[i]!=0)
printf("%d %d\n",i+1,(i+1)/zhouqi);
}
}
return 0;
}