• 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
  • 相关阅读:
    在springboot程序中自定义注解和反序列化实现
    文章相似度算法调研
    HTTP协议详解
    prototype.js 让你更深入的了解javascript的面向对象特性(转)
    ajax框架汇总
    prototype源码分析(转)
    c#中静态成员和实例成员(转)
    .NET中IDisposable接口的基本使用 (转)
    sql server 数据库优化(转)
    ADO.NET事物
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/8371261.html
Copyright © 2020-2023  润新知