Evanyou Blog 彩带

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$才去判断。

代码:

 

#include<bits/stdc++.h>
#define il inline
#define ll long long
#define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
using namespace std;
int t,n,next[1000005];
char s[1000005];

int main(){
    scanf("%d",&t);
    For(k,1,t){
        scanf("%d%s",&n,s);
        next[0]=next[1]=0;
        For(i,1,n-1){
            int p=next[i];
            while(p&&s[i]!=s[p]) p=next[p];
            next[i+1]=(s[i]==s[p]?p+1:0);
        }
        printf("Test case #%d\n",k);
        For(i,2,n) if(next[i]&&i%(i-next[i])==0) printf("%d %d\n",i,i/(i-next[i]));
        printf("\n");
    }
    return 0;
}

 

posted @ 2018-08-09 14:50  five20  阅读(249)  评论(0编辑  收藏  举报
Live2D