zoukankan      html  css  js  c++  java
  • UESTC_全都是秋实大哥 2015 UESTC Training for Search Algorithm & String<Problem J>

    J - 全都是秋实大哥

    Time Limit: 5000/2000MS (Java/Others)     Memory Limit: 32000/32000KB (Java/Others)
     

    秋实大哥是一个多愁善感的人,偶尔也会唱唱两句伤情的歌。每次唱完后,秋实大哥都能解决一道问题!这次也不例外。

    秋实大哥告诉了你 一些关于这个问题的信息

    如果一个字符串S是由若干个子串a连续拼接而成的,则称aS的循环节,即A=a+a+...+a。比如 aba 是 abaabaaba 的循环节。
    一个字符串可能存在多个循环节,比如 aaaaaaaa ,含有4个循环节,分别是 a , aa , aaaa , aaaaaaaa 。很显然,一个字符串是其本身的循环节。在这4个循环节中,长度最小的是"a",所以"a"是S的最小循环节。
    字符串所有循环节里长度最小的循环节,就是该字符串的最小循环节。
    一个长度为N的字符串,含有N个非空前缀。定义P(i)表示S的第i个非空前缀(0i<|S|)P(i)=S012...i。比如"abcde"含有5个非空前缀,分别是"a",“ab”,“abc”,“abcd”,“abcde”。

    现给一个字符串S,请先按顺序输出S的每一个非空前缀的最小循环节的长度,然后,再输出S的最小循环节。

    秋实大哥唱完了,问题也解决了,现在他请你来解决这个问题。

    Input

    第一行输入一个字符串S0<|S|3106),S只含有小写英文字母(a-z)

    Output

    第一行输出 |S| 个数,分别表示S的每一个非空前缀的最小循环节的长度,每两个数用一个空格隔开,最后一个数后面不要有空格。

    第二行输出一个字符串,表示S的最小循环节。

    Sample input and output

    Sample InputSample Output
    ab
    1 2
    ab
    aaaaaaaaa
    1 1 1 1 1 1 1 1 1
    a
    aaaaaaaad
    1 1 1 1 1 1 1 1 9
    aaaaaaaad
    abbaaddaabbaadda
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 8
    abbaadda
    abbaabbaabbaabba
    1 2 3 4 5 6 7 4 9 10 11 4 13 14 15 4
    abba

    解题报告:

    这是一道求最小循环节题目

     关键在于了解next数组的含义,next[i] 表示 0 - i-1的最大前缀后缀最大值,我们先假设它是循环的,那么显然满足i % (i - next[i]) == 0 , ( 长度是整数倍 ),之后next[i] != 0 (若为 0 ,此时前缀后缀的长度最大值0,也就是说,就是本身)

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    const int maxn = 3e6 + 500;
    char s[maxn];
    int len,front[maxn];
    
    void build_front()
    {
       front[0] = -1;
       int t1 = -1,t2 = 0;
       while(t2 < len)
        {
            if (t1 == -1 || s[t1] == s[t2])
             front[++t2] = ++ t1;
            else
             t1 = front[t1];
        }
    }
    
    int main(int argc,char *argv[])
    {
      scanf("%s",s);
      len = strlen(s);
      build_front();
      printf("1");
      for(int i = 2 ; i <= len ; ++ i)
       if (i % (i-front[i]) == 0 && front[i] != 0 )
        printf(" %d",i-front[i]);
       else
        printf(" %d",i);
      printf("
    ");
      if (len % (len-front[len]) == 0 && front[len] != 0)
       {
             int cot = len - front[len];
             for(int i = 0 ; i < cot ; ++ i)
              printf("%c",s[i]);
       }
      else
       printf("%s",s);
      printf("
    ");
      return 0;
    }
    No Pain , No Gain.
  • 相关阅读:
    2020年3月22日
    2021年3月21日
    2021年3月20日
    人件集阅读笔记02
    2021年3月19日
    2021年3月18日
    2021年3月17日
    2021年3月16日
    2021年3月15日
    梦断代码阅读笔记01
  • 原文地址:https://www.cnblogs.com/Xiper/p/4499176.html
Copyright © 2011-2022 走看看