zoukankan      html  css  js  c++  java
  • BZOJ3998:[TJOI2015]弦论——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3998

    https://www.luogu.org/problemnew/show/P3975

    对于一个给定长度为N的字符串,求它的第K小子串是什么。

    后缀自动机,对l排序然后从后往前推size和sum数组(貌似也可以叫拓扑?)。

    size:当前状态的字符串个数(贡献)。

    sum:以当前状态为起点之后的满足要求的字符串个数。

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    using namespace std;
    typedef long long ll;
    const int N=1e6+5;
    struct tree{
        int a[26],fa,l;
    }tr[N];
    char s[N];
    int last,cnt,t,k;
    ll a[N],w[N],size[N],sum[N];
    inline void insert(int c){
        int p=last,np=++cnt;
        last=np;tr[np].l=tr[p].l+1;
        for(;p&&!tr[p].a[c];p=tr[p].fa)tr[p].a[c]=np;
        if(!p)tr[np].fa=1;
        else{
        int q=tr[p].a[c];
        if(tr[p].l+1==tr[q].l)tr[np].fa=q;
        else{
            int nq=++cnt;tr[nq].l=tr[p].l+1;
            memcpy(tr[nq].a,tr[q].a,sizeof(tr[q].a));
            tr[nq].fa=tr[q].fa;tr[q].fa=tr[np].fa=nq;
            for(;p&&tr[p].a[c]==q;p=tr[p].fa)tr[p].a[c]=nq;
        }
        }
        size[np]=1;
    }
    int main(){
        scanf("%s%d%d",s,&t,&k);
        int len=strlen(s);
        last=cnt=1;
        for(int i=0;i<len;i++)insert(s[i]-'a');
        for(int i=1;i<=cnt;i++)w[tr[i].l]++;
        for(int i=1;i<=len;i++)w[i]+=w[i-1];
        for(int i=1;i<=cnt;i++)a[w[tr[i].l]--]=i;
        for(int i=cnt;i>=1;i--){
        if(t)size[tr[a[i]].fa]+=size[a[i]];
        else size[a[i]]=1;
        }
        size[1]=0;
        for(int i=cnt;i>=1;i--){
        sum[a[i]]=size[a[i]];
        for(int j=0;j<26;j++)
            if(tr[a[i]].a[j])
            sum[a[i]]+=sum[tr[a[i]].a[j]];
        }
        if(k>sum[1])puts("-1");
        else{
        int now=1;
        while(k>size[now]){
            k-=size[now];
            int i;
            for(int i=0;i<26;i++){
            if(k>sum[tr[now].a[i]])
                k-=sum[tr[now].a[i]];
            else{
                now=tr[now].a[i];
                putchar(i+'a');
                break;
            }
            }
        }
        puts("");
        }
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    jQuery 如何存储,获取和删除 Cookies
    mysql调用存储过程出现Illegal mix of collations错误
    vim IDE
    android 播放Raw文件夹下的音乐文件
    7种形式的Android Dialog使用举例
    Chronometer 计时器使用
    获取屏幕,适应屏幕
    android 碎片
    安卓开发者必备的42个链接
    自定义TabActivity,TabActivity的美化
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8776119.html
Copyright © 2011-2022 走看看