zoukankan      html  css  js  c++  java
  • TJOI2015 弦论

    题目描述

    题解:

    鉴于子串我们很容易想到后缀自动机。

    先建后缀自动机,然后处理单点价值以及对于每个点的总价值。

    T=0要求去重,此时单点价值为1;

    T=0要求不去重,此时单点价值为parent树上endpos的数量。后缀的前缀就是子串。

    由于建成的后缀自动机有向无环,我们可以O(n)时间处理每个点的总价值,即sum[u]+=sum[to]。

    时间复杂度O(n)。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 500050
    #define ll long long
    char s[N];
    int T,K;
    struct Point
    {
        int pre,len,trs[28];
    }p[2*N];
    struct SAM
    {
        int siz[2*N],v[2*N];
        ll sum[2*N];
        int tot,las;
        SAM(){tot=las=1;}
        int hed[2*N],cnt;
        struct EG
        {
            int to,nxt;
        }e[2*N];
        void ae(int f,int t)
        {
            e[++cnt].to = t;
            e[cnt].nxt = hed[f];
            hed[f] = cnt;
        }
        void insert(int c)
        {
            int np,nq,lp,lq;
            np=++tot;
            siz[np]=1;
            p[np].len = p[las].len+1;
            for(lp=las;lp&&!p[lp].trs[c];lp=p[lp].pre)
                p[lp].trs[c]=np;
            if(!lp)p[np].pre = 1;
            else
            {
                lq = p[lp].trs[c];
                if(p[lq].len==p[lp].len+1)p[np].pre = lq;
                else
                {
                    nq = ++tot;
                    p[nq] = p[lq];
                    p[nq].len = p[lp].len+1;
                    p[lq].pre = p[np].pre = nq;
                    while(p[lp].trs[c]==lq)
                    {
                        p[lp].trs[c]=nq;
                        lp=p[lp].pre;
                    }
                }
            }
            las = np;
        }
        void dfs1(int u)
        {
            v[u]=T?siz[u]:1;
            for(int j=hed[u];j;j=e[j].nxt)
            {
                int to = e[j].to;
                dfs1(to);
                if(T)v[u]+=v[to];
            }
        }
        void dfs2(int u)
        {
            sum[u] = v[u];
            for(int i=1;i<=26;i++)
            {
                int to = p[u].trs[i];
                if(!to)continue;
                if(!sum[to])dfs2(to);
                sum[u]+=sum[to];
            }
        }
        void build()
        {
            for(int i=2;i<=tot;i++)
                ae(p[i].pre,i);
            dfs1(1);
            v[1]=0;
            dfs2(1);
        }
        void cal(int k)
        {
            int u = 1;
            if(sum[1]<k)
            {
                printf("-1");
                return ;
            }
            while(1)
            {
                for(int i=1;i<=26;i++)
                {
                    if(k>sum[p[u].trs[i]])k-=sum[p[u].trs[i]];
                    else
                    {
                        printf("%c",'a'+i-1);
                        u = p[u].trs[i];
                        k-= v[u];
                        break;
                    }
                }
                if(k<=0)return ;
            }
        }
    }sam;
    int main()
    {
        scanf("%s%d%d",s+1,&T,&K);
        int len = strlen(s+1);
        for(int i=1;i<=len;i++)
            sam.insert(s[i]-'a'+1);
        sam.build();
        sam.cal(K);
        printf("
    ");
        return 0;
    }
  • 相关阅读:
    变长参数表
    以二进制方式输出数字在内存中的存储形式
    asp.net mvc controller 获取数据
    asp.net mvc 3.0 新特性之 Model
    一个实体对象不能由多个 IEntityChangeTracker 实例引用
    iis6.0运行asp请求资源正在使用中
    view的使用
    asp.net mvc RenderAction 和RenderPartial用法
    今天
    当下的力量
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10098115.html
Copyright © 2011-2022 走看看