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

    bzoj3670[Noi2014]动物园

    题意:

    对于字符串S的前i个字符构成的子串,既是它的后缀同时又是它的前缀,并且该后缀与该前缀不重叠,将这种字符串的数量记作num[i]。给出字符串S求所有num[i]+1的乘积模1000000007。字符串长度≤1000000

    题解:

    先求一遍fail函数,得到数组记为next1,然后再求next2数组,表示满足next1[j]*2≤i的next1[j],这一过程也是可以递推的。同时用cnt数组记录next1[j]有多少个。num[i]就是cnt[next2[i]]。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define maxn 1000100
     5 #define inc(i,j,k) for(int i=j;i<=k;i++)
     6 #define mod 1000000007
     7 using namespace std;
     8 
     9 char s[maxn]; int next1[maxn],next2[maxn],cnt[maxn],t,len; long long ans;
    10 int main(){
    11     scanf("%d",&t);
    12     while(t--){
    13         scanf("%s",s+1); len=strlen(s+1); next1[1]=0; cnt[1]=1; next2[1]=0;
    14         inc(i,2,len){
    15             int j=next1[i-1]; while(j&&s[j+1]!=s[i])j=next1[j];
    16             if(s[j+1]==s[i])next1[i]=j+1,cnt[i]=cnt[next1[i]]+1;else next1[i]=0,cnt[i]=1;
    17         }
    18         inc(i,2,len){
    19             int j=next2[i-1]; if(j*2+2>i)j=next1[j]; while(j&&s[j+1]!=s[i])j=next1[j];
    20             if(s[j+1]==s[i])next2[i]=j+1;else next2[i]=0;
    21         }
    22         ans=1; inc(i,1,len)ans=ans*(cnt[next2[i]]+1)%mod; printf("%lld
    ",ans);
    23     }
    24     return 0;
    25 }

    20160806

  • 相关阅读:
    【如何在mysql 官网下载最新版本mysql 数据库】
    【17-类加载与反射】
    【16-网络编程】
    【14-输入/输出】
    【13-Annotation】
    【12-JDBC编程】
    C# SqlHelper类的数据库操作
    C# DateTime与时间戳转换
    C#递归方法遍历目录及子目录
    C# SaveFileDialog的用法
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/5808565.html
Copyright © 2011-2022 走看看