【GDOI2012】字符串

来源:互联网 发布:c语言培训班 编辑:程序博客网 时间:2024/06/15 13:30

Description

mmm正在学习字典序。现在老师给她布置了一个作业:给出一个字符串,问该字符串的所有不同的子串中,按字典序排第K的字串。由于众所周知的原因,mmm需要你为她解决这个问题。

Solution

这里与TJOI2015弦论几乎是一样的,比那题还要水很多。
根本就不用担心爆栈什么的。
后缀自动机直接秒过。

Code

#include<iostream> #include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)using namespace std;const int maxn=20007;int i,j,k,l,n,m,ans;char s[maxn];struct node{    int len,fa,son[26],sum;}t[maxn*2];int a[maxn*2],b[maxn*2],c[maxn*2];int last,num,np,p,q,nq;void extend(int c){    np=++num,p=last;    t[np].len=t[p].len+1;    while(p&&!t[p].son[c])t[p].son[c]=np,p=t[p].fa;    if(!p)t[np].fa=1;    else{        q=t[p].son[c];        if(t[p].len+1==t[q].len)t[np].fa=q;        else{            nq=++num;            t[nq]=t[q];            t[nq].len=t[p].len+1;            t[q].fa=t[np].fa=nq;            while(p&&t[p].son[c]==q)t[p].son[c]=nq,p=t[p].fa;        }    }    last=np;}void dfs(int x,int k){    if(k<=c[x])return;    k-=c[x];    int j;    fo(j,0,25){        if(t[x].son[j]){            if(k<=t[t[x].son[j]].sum){                putchar(j+'a');                dfs(t[x].son[j],k);                return;            }            k-=t[t[x].son[j]].sum;        }    }}int main(){    scanf("%s",s+1);    n=strlen(s+1);    last=num=1;    fo(i,1,n)extend(s[i]-'a');    fo(i,1,num)a[t[i].len]++;    fo(i,1,n)a[i]+=a[i-1];    fod(i,num,1)b[a[t[i].len]--]=i;    fo(i,2,num)c[i]=1;    fod(i,num,1){        int u=b[i];t[u].sum=c[u];        fo(j,0,25){            t[u].sum+=t[t[u].son[j]].sum;        }    }    scanf("%d",&m);    fo(i,1,m){        scanf("%d",&k);        if(t[1].sum<k)printf("-1\n");        else {            dfs(1,k);            printf("\n");        }    }}
1 0