zoukankan      html  css  js  c++  java
  • bzoj3998 [TJOI2015]弦论

    后缀自动机

    我们建出后缀自动机,对于每个节点我们算出他和他的后继结点一共可以形成多少个不同的串,不同根据t来定义

    这里我们不需要考虑每个节点代表的那些等价类字符串,因为那些字符串不同的前缀在到达这个节点前已经确定了,所以我们只需要在t=1时一下考虑right集合的大小,right集合的大小需要在parent树上pushup,乱搞一下就好了。

    最后dfs一下即可。

    发现bzoj榜上的时间都很接近,于是就在Troywar的帮助下卡了波常,然而只到了第一页,并没有快多少。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #define N 1000500
     7 using namespace std;
     8 int n,m,o;
     9 char s[N>>1];
    10 int last,tot,mx[N],par[N],ch[N][26];
    11 int val[N],sum[N],buc[N],q[N];
    12 void add(int c){
    13     int p=last,np=++tot;
    14     mx[np]=mx[p]+1;val[np]=1;
    15     for(;p&&!ch[p][c];p=par[p])ch[p][c]=np;
    16     if(!p)  par[np]=1;
    17     else{
    18         int q=ch[p][c];
    19         if(mx[q]==mx[p]+1)par[np]=q;
    20         else{
    21             int nq=++tot;
    22             mx[nq]=mx[p]+1;
    23             par[nq]=par[q];
    24             memcpy(ch[nq],ch[q],sizeof ch[nq]);
    25             par[q]=par[np]=nq;
    26             for(;p&&ch[p][c]==q;p=par[p])ch[p][c]=nq;
    27         }
    28     }last=np;
    29 }
    30 void init(){
    31     for(int i=1;i<=tot;i++)buc[mx[i]]++;
    32     for(int i=1;i<=n;i++)buc[i]+=buc[i-1];
    33     for(int i=tot;i;i--)q[buc[mx[i]]--]=i;
    34     for(int i=tot;i;i--){
    35         if(!o)val[q[i]]=1;
    36         else val[par[q[i]]]+=val[q[i]];
    37     }val[1]=0;
    38     for(int i=tot;i;i--){
    39         sum[q[i]]=val[q[i]];
    40         for(int j=0;j<26;j++)
    41             sum[q[i]]+=sum[ch[q[i]][j]];
    42     }
    43 }
    44 void dfs(int x,int k){
    45     if(k<=val[x])return ;
    46     k-=val[x];
    47     for(int i=0;i<26;i++)if(ch[x][i]){
    48         if(sum[ch[x][i]]>=k){
    49             putchar(i+'a');
    50             dfs(ch[x][i],k);
    51             return ;
    52         }k-=sum[ch[x][i]];
    53     }
    54 }
    55 int main(){
    56     last=++tot;
    57     scanf("%s",s+1);
    58     n=strlen(s+1);
    59     for(int i=1;i<=n;i++)add(s[i]-'a');
    60     scanf("%d%d",&o,&m);
    61     init();
    62     if(m>sum[1])puts("-1");
    63     else dfs(1,m);
    64 }
    View Code
  • 相关阅读:
    php使用redis锁
    php接收json数据
    计算机中的二进制、八进制、十进制、十六进制
    mysql8导入myslq5 报错
    如何用最简单的方式解释依赖注入?依赖注入是如何实现解耦的?(通俗易懂)
    【运维】Linux进阶命令简记--Linux(3)
    springboot项目在docker容器中如何优雅关闭
    springboot项目接入sap与部署到docker遇到的问题实录
    如何解决springboot参数传中文乱码
    maven如何动态统一修改版本号
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/8371261.html
Copyright © 2011-2022 走看看