• 洛谷 SP263 Period


    洛谷 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* , 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.

    题意翻译

    如果一个字符串S是由一个字符串T重复K次形成的,则称T是S的循环元。使K最大的字符串T称为S的最小循环元,此时的K称为最大循环次数。

    现给一个给定长度为N的字符串S,对S的每一个前缀S[1~i],如果它的最大循环次数大于1,则输出该前缀的最小循环元长度和最大循环次数。

    感谢@super_kidding 提供的翻译

    输入输出样例

    输入 #1复制

    输出 #1复制


    一道KMP算法的练手好题。

    大体的题目大意是这样的:

    题目大意:

    如果一个字符串S是由一个字符串T重复K次形成的,则称T是S的循环元。使K最大的字符串T称为S的最小循环元,此时的K称为最大循环次数。

    现给一个给定长度为N的字符串S,对S的每一个前缀S[1~i],如果它的最大循环次数大于1,则输出该前缀的最小循环元长度和最大循环次数。

    题解:

    一道KMP算法的题目,如果对KMP算法还是没有什么深刻的理解或者还没学KMP算法的,请移步我的这篇博客,讲解还算详细:

    KMP算法详解

    一开始拿到题没什么思路(我还是太菜了)

    后来发现,对给出的串(S)自匹配求出(nxt)数组之后,对于每一个(i),一定会有这么一个结论:

    [S[1\,\,to\,\,nxt[i]]=S[i-nxt[i]+1\,\,to\,\,i] ]

    这是通过KMP算法对(nxt)数组的定义得来的。

    那么,既然这两个东西是相等的,那么在对这个子串进行匹配的时候,这个循环节长度就应该是(i-nxt[i]),然后循环次数当然就是(i/(i-nxt[i])),当然,前提需要是(i\%(i-nxt[i])==0)

    代码如下:

    #include<cstdio>
    using namespace std;
    const int maxl=1e6+10;
    int n,tot;
    char s[maxl];
    int nxt[maxl];
    int main()
    {
        while(~scanf("%d",&n) && n)
        {
            scanf("%s",s+1); 
            tot++;
            printf("Test case #%d
    ",tot);
            nxt[1]=0;
            for(int i=2,j=0;i<=n;++i)
            {
                while(s[i]!=s[j+1] && j) 
                    j=nxt[j];
                if(s[i]==s[j+1]) 
                    j++;
                nxt[i]=j;
                if(nxt[i]!=0 && i%(i-nxt[i])==0) 
                    printf("%d %d
    ",i,i/(i-nxt[i]));
            }
            printf("
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    Jquery中的this指向的是哪个对象?
    需要重新编辑
    关于CSS选择器优先级无冲突样式设置的展示
    在 CSS 中,width 和 height 指的是内容区域的宽度和高度
    关于正则表达式中分组的一些误解勘正以及String的replaceAll方法误解勘正
    关于informatica的Dynamic Lookup组件使用中遇到的一个问题的思考
    【转】Informatica Update 机制详解
    维度表和事实表的含义
    今天看IO流,复制word遇到的一个小问题
    小试下新博客,一个列传行的SQL
  • 原文地址:https://www.cnblogs.com/fusiwei/p/11945334.html
Copyright © 2020-2023  润新知