zoukankan      html  css  js  c++  java
  • [模拟赛FJOI Easy Round #2][T1 sign] (模拟+求字符串重复字串)

    【题目描述】

    小Z在无意中发现了一个神奇的OJ,这个OJ有一个神奇的功能:每日签到,并且会通过某种玄学的算法计算出今日的运势。在多次试验之后,小Z发现自己的运势按照一定的周期循环,现在他找到了你,请通过他的记录,找出他运势的循环节。

    【输入数据】

    第一行一个整数n,表示小Z记录的天数

    接下来n行,表示每天的运势,用一个正整数表示,相同的整数表示相同的运势,不同的整数表示不同的运势。

    【输出数据】

    一行若干个整数表示所有可能的小于等于n的循环节。

    【样例输入】

    6

    1 2 1 1 2 1

    【样例输出】

    3 5 6

    【数据范围】

    对于100%的数据,n<=365,每天的运势不会爆int

    Solution

    果然是签到题。

    当然最暴力的解法是O(n*n*n)

    这里数据范围比较小,我们考虑O(n*n)的算法

    先枚举重复串的长度,判断时,用错位比较法

    如果当前枚举的长度为k,匹配后缀S(1)和后缀S(k+1)的最长公共前缀是n-k的话,证明k是一个符合本题题意的循环节

    要优化的话不能用后缀数组,用个kmp吧,我倒是直接暴力了

    #include<stdio.h>
    #include<string.h>
    #define N 400
    inline int Rin(){
      int x=0,c=getchar(),f=1;
      for(;c<48||c>57;c=getchar())
        if(!(c^45))f=-1;
      for(;c>47&&c<58;c=getchar())
        x=(x<<1)+(x<<3)+c-48;
      return x*f;
    }
    int n,a[N],top,pb[N];
    inline bool jud(int k){
      for(int i=1;i<=n-k;i++)
        if(a[i]^a[k+i])
          return false;
      return true;
    }
    int main(){
      freopen("sign.in","r",stdin);
      freopen("sign.out","w",stdout);
      n=Rin();
      for(int i=1;i<=n;i++)
        a[i]=Rin();
      for(int i=1;i<n;i++)
        if(jud(i))
          pb[++top]=i;
      for(int i=1;i<=top;i++)
        printf("%d ",pb[i]);
      printf("%d
    ",n);
      fclose(stdin);
      fclose(stdout);
      return 0;
    }
  • 相关阅读:
    C语言 strcat
    C语言 strncpy
    C语言 strcpy
    C语言 main
    可显示Android设备选择列表,并进入指定Android设备Console的Shell脚本
    Android系统如何录制屏幕(录制成mp4格式)
    据说有99%的人都会做错的面试题
    一道淘汰85%面试者的百度开发者面试题
    用Android模拟器也可以开发和测试NFC应用
    一道腾讯面试题的思考:到底谁会赢?
  • 原文地址:https://www.cnblogs.com/keshuqi/p/6262416.html
Copyright © 2011-2022 走看看