zoukankan      html  css  js  c++  java
  • SP263 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
    ",k);
            For(i,2,n) if(next[i]&&i%(i-next[i])==0) printf("%d %d
    ",i,i/(i-next[i]));
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    感性的记录一次生活
    CF 696 A Lorenzo Von Matterhorn(二叉树,map)
    UVA 673 Parentheses Balance(栈)
    POJ 1363 Rails(栈)
    HDU 1314 Numerically Speaking(大数加减乘除+另类二十六进制互相转换)
    UVA 540 Team Queue(模拟+队列)
    HDU 1276 士兵队列训练问题(模拟)
    CF 480 B Long Jumps (map标记)
    UVA 136 Ugly Numbers
    HDU 1027 Ignatius and the Princess II
  • 原文地址:https://www.cnblogs.com/five20/p/9448899.html
Copyright © 2011-2022 走看看