zoukankan      html  css  js  c++  java
  • UOJ #5. 【NOI2014】动物园 扩大KMP


    第一次NOI称号。

    。。。

    扩展假设知道KMP如果。

    。。

    就是水题了。

    。。。

    #5. 【NOI2014】动物园

    统计提交情况

    近日。园长发现动物园中好吃懒做的动物越来越多了。比如企鹅。仅仅会卖萌向游客要吃的。

    为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的园长决定开设算法班。让动物们学习算法。 某天,园长给动物们解说KMP算法。

    园长:“对于一个字符串S它的长度为L。我们能够在O(L)的时间内求出一个名为next的数组。有谁预习了next数组的含义吗?”

    熊猫:“对于字符串S的前i个字符构成的子串,既是它的后缀又是它的前缀的字符串中,它本身除外。最长的长度记作 next[i]。”

    园长:“很好,那你能举个样例吗?

    熊猫:“比如Sabcababc,则next[5]=2。

    由于S的前5个字符为abcabab既是它的后缀又是它的前缀,而且找不到一个更长的字符串满足这个性质。

    同理,还可得出 next[1] = next[2] = next[3] = 0, next[4] = next[6] = 1, next[7] = 2, next[8] = 3。

    园长表扬了认真预习的熊猫同学。

    随后,他具体解说了怎样在O(L)的时间内求出next数组。下课前。园长提出了一个问题:“KMP算法仅仅能求出next数组。我如今希望求出一个更强大num数组——对于字符串S的前i个字符构成的子串,既是它的后缀同一时候又是它的前缀,而且该后缀与该前缀不重叠,将这样的字符串的数量记作num[i]。比如Saaaaa,则num[4]=2。

    这是由于S的前4个字符为aaaa,当中aaa都满足性质‘既是后缀又是前缀’。同一时候保证这个后缀与这个前缀不重叠。

    aaa尽管满足性质‘既是后缀又是前缀’。但遗憾的是这个后缀与这个前缀重叠了。所以不能计算在内。同理。num[1]=0,num[2]=num[3]=1,num[5]=2。

    最后。园长给出了奖励条件,第一个做对的同学奖励巧克力一盒。听了这句话,睡了一节课的企鹅立马就醒过来了。但企鹅并不会做这道题。于是向參观动物园的你寻求帮助。你是否能帮助企鹅写一个程序求出num数组呢?

    特别地,为了避免大量的输出。你不须要输出num[i]各自是多少,你仅仅须要输出 Li=1(num[i]+1)1000000007取模的结果就可以。

    当中ni=1(num[i]+1)=(num[1]+1)×(num[2]+1)××(num[n]+1)

    输入格式

    输入文件的第1行仅包括一个正整数n

    表示測试数据的组数。 随后n行。每行描写叙述一组測试数据。

    每组測试数据仅含有一个字符串SS的定义详见题目描写叙述。

    数据保证S,中仅含小写字母。输入文件里不会包括多余的空行,行末不会存在多余的空格。

    输出格式

    输出文件应包括n

    每行描写叙述一组測试数据的答案

    答案的顺序应与输入数据的顺序保持一致。对于每组測试数据。仅须要输出一个整数。表示这组測试数据的答案对1000000007取模的结果。

    输出文件里不应包括多余的空行

    例子一

    input

    3
    aaaaa
    ab
    abcababc
    
    

    output

    36
    1
    32
    
    

    例子二

    见“例子数据下载”

    限制与约定

    測试点编号 约定
    1 n5,L50
    2 n5,L200
    3 n5,L200
    4 n5,L10000
    5 n5,L10000
    6 n5,L100000
    7 n5,L200000
    8 n5,L500000
    9 n5,L1000000
    10 n5,L1000000

    时间限制:1s

    空间限制:512MB

    下载

    例子数据下载


    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long int LL;
    const int maxn=1001000;
    const LL MOD=1000000007;
    
    char P[maxn];
    int next[maxn],n;
    
    void pre_exkmp(char P[])
    {
      int m=strlen(P);
      next[0]=m;
      int j=0,k=1;
      while(j+1<m&&P[j]==P[j+1])j++;
      next[1]=j;
      for(int i=2;i<m;i++)
        {
          int p=next[k]+k-1;
          int L=next[i-k];
          if(i+L<p+1) next[i]=L;
          else
            {
              j=max(0,p-i+1);
              while(i+j<m&&P[i+j]==P[j]) j++;
              next[i]=j; k=i;
            }
        }
    }
    
    int xxx[maxn];
    
    int main()
    {
      int T_T;
      scanf("%d",&T_T);
      while(T_T--)
        {
          memset(xxx,0,sizeof(xxx));
          memset(next,0,sizeof(next));
          scanf("%s",P);
          n=strlen(P);
          pre_exkmp(P);
          for(int i=1;i<n;i++)
            {
              if(next[i])
                {
                  xxx[i]++;
                  int t1=i+next[i];
                  int t2=2*i;
                  xxx[min(t1,t2)]--;
                }
              next[i]=0;
            }
          LL ans=1;
          LL now=0;
          for(int i=0;i<n;i++)
            {
              now+=xxx[i];
              ans=(ans*(now+1))%MOD;
            }
          cout<<ans<<endl;
        }
      return 0;
    }
    





    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    FreeCommander 学习手册
    String详解, String和CharSequence区别, StringBuilder和StringBuffer的区别 (String系列之1)
    StringBuffer 详解 (String系列之3)
    StringBuilder 详解 (String系列之2)
    java io系列26之 RandomAccessFile
    java io系列25之 PrintWriter (字符打印输出流)
    java io系列24之 BufferedWriter(字符缓冲输出流)
    java io系列23之 BufferedReader(字符缓冲输入流)
    java io系列22之 FileReader和FileWriter
    java io系列21之 InputStreamReader和OutputStreamWriter
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4711759.html
Copyright © 2011-2022 走看看