• [bzoj3670] [Noi2014]动物园


      初二那时候这题成功0分。

      然而现在对于复杂度还是有点乱。。。

      暴力做法的话。。显然就是使劲在fail树上跳,看fail链上有多少个<=长度/2的节点。

      如果对于fail树上的节点,记录一下根到它的节点数的话。。每次查询的时候我们只要找到刚好<=长度/2的那个分界点就行了。

      对于一条fail链,分界点显然是随着深度而单调的。。。所以每次从fail链最末的节点开始,把整条链都扒出来,利用分界点的单调性求解。

      复杂度的话。。并不是严格O(n)...要看这些fail链有多少节点会被重复计算。

      比方说。。字符串 aaaaaa.......如果后面有很多个节点的fail都指向那一坨'a'的末端的话。。。

      似乎就会有很多重复计算,但实际上最末的那个'a'一定是分界点。

      因为fail的大小的增长是线性的...每往后一位,fail的大小最多+1

      所以大概复杂度就不用担心了吧= =

    速度极慢,应该是比较丑的。。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #define ll long long
     5 using namespace std;
     6 const int maxn=1000233;
     7 const ll modd=1000000007;
     8 char s[maxn];
     9 int fail[maxn],sm[maxn],st[maxn],top;
    10 int i,j,k,n,m,l;
    11 ll an,ans[maxn];
    12 bool u[maxn];
    13 
    14 inline void getfail(int n){
    15     int i,p=0;fail[1]=0;
    16     for(i=2;i<=n;i++){
    17         while(p&&s[p+1]!=s[i])p=fail[p];
    18         p+=s[p+1]==s[i],fail[i]=p;
    19     }
    20 }
    21 int main(){
    22     int T;scanf("%d",&T);
    23     for(int ii=1;ii<=T;ii++){
    24         
    25         scanf("%s",s+1);
    26     //    for(i=1;i<=1000000;i++)if(i&2)s[i]='b';else s[i]='a';
    27         s[0]='%';n=strlen(s)-1;
    28         if(ii>1)memset(sm,0,(n+1)<<2),memset(u,0,n+1);
    29         getfail(n);
    30         for(i=1;i<=n;i++)sm[i]=sm[fail[i]]+1;
    31         
    32         for(i=n;i;i--)if(!u[i])
    33             if((fail[i]<<1)<=i)u[i]=1,ans[i]=sm[fail[i]];
    34             else{
    35                 for(st[top=1]=j=i;fail[j];st[++top]=(j=fail[j]));
    36                 l=top+1;st[top+1]=0;
    37                 for(j=top;j;j--){
    38                     while((st[l-1]<<1)<=st[j])l--;
    39                     ans[st[j]]=sm[st[l]];
    40                     u[st[j]]=1;
    41                 }
    42             }
    43         for(i=an=1;i<=n;i++){
    44             an*=ans[i]+1;
    45             if(an>=modd)an%=modd;
    46         //    printf("  %d %lld
    ",i,ans[i]);
    47         }
    48         printf("%lld
    ",an);
    49     }
    50     return 0;
    51 }
    View Code
  • 相关阅读:
    【干货分享】C# 实体类生成工具
    ASP.NET Core部署系列二:发布到CentOS上
    ASP.NET Core部署系列一:发布到IIS上
    微信公众号开发:用户管理
    微信公众号开发:自定义菜单
    像使用SQL一样对List对象集合进行排序
    使用JRebel插件实现SpringBoot应用代码热加载
    Java Stream函数式编程图文详解(二):管道数据处理
    SpringBoot生命周期管理之停掉应用服务几种方法
    本月16日SpringBoot2.2发布,有哪些变化先知晓
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5330879.html
Copyright © 2020-2023  润新知