SP263 PERIOD - Period

题目描述

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 ^{K} K , that is A concatenated K times, for some string A. Of course, we also want to know the period K.

输入输出格式

输入格式:

The first line of the input file will contains only the number T (1 <= T <= 10) of the 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.

输出格式:

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.

输入输出样例

输入样例#1: 
2
3
aaa
12
aabaabaabaab
输出样例#1: 
Test case #1
2 2
3 3

Test case #2
2 2
6 2
9 3
12 4
 

Solution:

  题意就是求一个字符串的所有循环前缀的最大周期数(周期个数不能为1)。

  这种字符串的周期问题,下意识想到去求所有前缀的最长公共前后缀(next数组),考虑到next的性质:$S|0~next[i]|=S|i-next[i]+1~i|$,当字符串$S|0~i|$存在循环周期时,必定存在$(i-next[i])|i$(反之亦然),即错位部分$S|next[i]~i|$一定是一个周期且是最小周期(因为是最长公共前后缀),那么周期数最多就是$\frac{i}{i-next[i]}$,由于题目中周期不能为本身,所以$next[i]$必须大于$0$才去判断。

代码:

 1 #include<bits/stdc++.h>
 2 #define il inline
 3 #define ll long long
 4 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
 5 #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
 6 using namespace std;
 7 int t,n,next[1000005];
 8 char s[1000005];
 9 
10 int main(){
11     scanf("%d",&t);
12     For(k,1,t){
13         scanf("%d%s",&n,s);
14         next[0]=next[1]=0;
15         For(i,1,n-1){
16             int p=next[i];
17             while(p&&s[i]!=s[p]) p=next[p];
18             next[i+1]=(s[i]==s[p]?p+1:0);
19         }
20         printf("Test case #%d\n",k);
21         For(i,2,n) if(next[i]&&i%(i-next[i])==0) printf("%d %d\n",i,i/(i-next[i]));
22         printf("\n");
23     }
24     return 0;
25 }

题目描述

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 ^{K} K , that is A concatenated K times, for some string A. Of course, we also want to know the period K.

输入输出格式

输入格式:

The first line of the input file will contains only the number T (1 <= T <= 10) of the 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.

输出格式:

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.

输入输出样例

输入样例#1: 复制
2
3
aaa
12
aabaabaabaab
输出样例#1: 复制
Test case #1
2 2
3 3

Test case #2
2 2
6 2
9 3
12 4

猜你喜欢

转载自www.cnblogs.com/five20/p/9448899.html