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;
    }
  • 相关阅读:
    9-10-堆 Windows消息队列(25 分)
    9-7 二叉搜索树的结构(30 分)
    9-4 笛卡尔树(25 分)
    9-3 搜索树判断(25 分)
    7-9 堆中的路径(25 分)
    个人总结
    软工网络15个人作业4——alpha阶段个人总结
    软件工程网络15个人作业3——案例分析(201521123029 郑佳明)
    软件工程15 结对编程作业
    软件工程网络15个人阅读作业2(201521123029 郑佳明)
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10098115.html
Copyright © 2011-2022 走看看