zoukankan      html  css  js  c++  java
  • [bzoj3670][Noi2014]动物园

    Description

    已知一个字符串S,对于字符串S的前i个字符构成的子串,既是它的后缀同时又是它的前缀,并且该后缀与该前缀不重叠,将这种字符串的数量记作num[i]

    mod 109+7

    Input

    1行仅包含一个正整数n,表示测试数据的组数。随后n行,每行描述一组测试数据。每组测试数据仅含有一个字符串SS的定义详见题目描述。数据保证S中仅含小写字母。输入文件中不会包含多余的空行,行末不会存在多余的空格。

    Output

    包含n行,每行描述一组测试数据的答案,答案的顺序应与输入数据的顺序保持一致。对于每组测试数据,仅需要输出一个整数,表示这组测试数据的答案mod 109+7的结果。

    Sample Input

    3
    aaaaa
    ab
    abcababc

    Sample Output

    36
    1
    32

    HINT

    n≤5,L≤16

    Solution

    题意就是给你一个字符串S,对于这个字符串S的每一个前缀S[1...i]next[j]满足j×2<=i的个数记作num[i],求num[i]

    那么,就先思考问题的简化版,在没有j×2<=i的限制下,num[i]=num[next[i]]+1,将这种情况下的num[]记作cnt[]

    现在问题就变成了,如何不用O(n2)的算法求满足条件的j

    我们可以再用kmp的思想完成这件事,当发现现在的j不满足条件时,可以用next[]向前寻找满足条件的j

    这样的话,每次都是从满足j×2<=i-1j开始寻找,避免了一些重复向前找的时间复杂度,于是就A了。

     1 #include<set> 
     2 #include<cmath>
     3 #include<ctime>
     4 #include<queue>
     5 #include<stack>
     6 #include<cstdio>
     7 #include<vector> 
     8 #include<string>
     9 #include<cstring>
    10 #include<cstdlib>
    11 #include<iostream>
    12 #include<algorithm>
    13 #define N 1000002
    14 #define M 1000000007
    15 using namespace std;
    16 int t[N],cnt[N],next[N],n,m;
    17 long long ans;
    18 char a[N];
    19 inline void get_next(){
    20     for(int i=2,j=0;i<=m;i++){
    21         while(j&&a[i]!=a[j+1]) j=next[j];
    22         j+=(a[i]==a[j+1]);
    23         next[i]=j;
    24         cnt[i]=cnt[j]+1;
    25     }
    26 }
    27 inline void init(){
    28     scanf("%d",&n);cnt[1]=1;
    29     for(int l=1;l<=n;l++){
    30         scanf("%s",a+1);
    31         m=strlen(a+1);
    32         fill(next+1,next+1+m,0);
    33         get_next();ans=1;
    34         for(int i=2,j=0;i<=m;i++){
    35             while(j&&a[i]!=a[j+1]) j=next[j]; 
    36             if(a[i]==a[j+1]) j++;
    37             while(j*2>i) j=next[j];
    38             ans=ans*(cnt[j]+1)%M;
    39         }
    40         printf("%lld
    ",ans);
    41     }
    42     
    43 }
    44 int main(){
    45     freopen("zoo.in","r",stdin);
    46     freopen("zoo.out","w",stdout);
    47     init();
    48     fclose(stdin);
    49     fclose(stdout);
    50     return 0;
    51 }
  • 相关阅读:
    php基础之简单运算
    选择平淡
    php基础之控制结构
    关于三元运算符的初步应用及理解
    VS2015 遇到异常。这可能是由某个扩展导致的
    C#中如何去除窗体默认的关闭按钮
    (转载)SQL基础--> 约束(CONSTRAINT)
    SQL Server安装后设置SQL Server验证登录
    附加数据库 对于 ""失败,无法打开物理文件 操作系统错误 5:拒绝访问 SQL Sever
    SQL Server数据库操作(二)
  • 原文地址:https://www.cnblogs.com/AireenYe/p/5598022.html
Copyright © 2011-2022 走看看