POJ 1961 Period
Period
Time Limit: 3000MS Memory Limit: 30000K
Total Submissions: 10770 Accepted: 4955
Description
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 AK ,that is A concatenated K times, for some string A. Of course, we also want to know the period K.
Input
The input consists of several test cases. Each test case consists of two lines. The first one contains N (2 <= N <= 1 000 000) – the size of the string S.The second line contains the string S. The input file ends with a line, having the
number zero on it.
Output
For each test case, output "Test case #" and the consecutive test case number on a single line; then, for each prefix with length i that has a period K > 1, output the prefix size i and the period K separated by a single space; the prefix sizes must be in increasing order. Print a blank line after each test case.
Sample Input
3
aaa
12
aabaabaabaab
0Sample Output
Test case #1
2 2
3 3
Test case #2
2 2
6 2
9 3
12 4Source
Southeastern Europe 2004
一开始看这题的时候真的是没有多少思路,只能可能与KMP中的next有关,但是确实没有多少思路,过了好多天,几天突然有了思路。完全可以分三种情况
(1)假设他的next的长度的2倍,正好覆盖字符串,则这个长度就是所求。
(2)假设长度2倍数,不能覆盖,则没有解
(3)假设出线交集,即他的答案等于next长度所对应的答案。 next长度所对应的答案,可以记录一下。
[cpp]
/***************************************************************
> File Name: E:\我的程序\C语言\period.c
> Author: SDUT_GYX
> Mail: 2272902662@qq.com
> Created Time: 2013/5/8 11:18:25
**************************************************************/
#include<stdio.h>
#include <string.h>
#include <math.h>
int dp[11000000],next[1100000];
char s1[1100000];
int main()
{
void get_next(int l);
int i,j,n,m,s,t,l;
t=1;
while(scanf("%d",&n)!=EOF)
{
if(n==0)
{
break;
}
scanf("%s",s1);
get_next(n);
dp[0]=0;
printf("Test case #%d\n",t++);
for(i=2;i<=n;i++)
{
l=next[i];
if(l+l==i)
{
printf("%d %d\n",i,i/l);
dp[i-1]=l;
}else if(l+l<i)
{
dp[i-1]=0;
}else
{
if(dp[l-1]!=0)
{
printf("%d %d\n",i,i/dp[l-1]);
dp[i-1]=dp[l-1];
}else
{
dp[i-1]=0;
}
}
}
printf("\n");
}
return 0;
}
void get_next(int l)
{
int i,j;
next[0]=-1;
next[1]=0;
for(i=2,j=0; i<=l; )
{
if(j==-1||s1[i-1]==s1[j])
{
i++; j++;
next[i-1]=j;
}else
{
j=next[j];
}
}
}
/***************************************************************
> File Name: E:\我的程序\C语言\period.c
> Author: SDUT_GYX
> Mail: 2272902662@qq.com
> Created Time: 2013/5/8 11:18:25
**************************************************************/
#include<stdio.h>
#include <string.h>
#include <math.h>
int dp[11000000],next[1100000];
char s1[1100000];
int main()
{
void get_next(int l);
int i,j,n,m,s,t,l;
t=1;
while(scanf("%d",&n)!=EOF)
{
if(n==0)
{
break;
}
scanf("%s",s1);
get_next(n);
dp[0]=0;
printf("Test case #%d\n",t++);
for(i=2;i<=n;i++)
{
l=next[i];
if(l+l==i)
{
printf("%d %d\n",i,i/l);
dp[i-1]=l;
}else if(l+l<i)
{
dp[i-1]=0;
}else
{
if(dp[l-1]!=0)
{
printf(&
补充:软件开发 , C++ ,