spoj7258 Lexicographical Substring Search(SUBLEX) 后缀自动机

来源:互联网 发布:2016年淘宝卖家数量 编辑:程序博客网 时间:2024/05/06 04:09

    给一个字符串S,若干个查询,每个查询k输出字典序第k小的S的子串。把字符串一次插入到自动机中,由于在不考虑父边的情况下,可以看做一个有向无环图,那么我们可在在这个图上进行dp,令dp[i]表示从节点i开始有多少个子串,转移dp[i]=dp[j]+1(存在一条边c使得i-->j),然后就是从根节点贪心走一遍就可以得到要求的串了。

   另外吐槽一句SPOJ上的题卡时间卡的太凶残了....

#include <iostream>#include <cstdio>#include <memory.h>#include <algorithm>#include <string>#include <cstring>#include <stack>using namespace std;const int maxn=180010;const int S=26;int next[maxn][26];char ch[maxn][26];char str[maxn>>1];int wtop[maxn];int cnt[maxn];int n,m,q;int len,tot;struct node{    node *par,*go[S];    int val,cnt;}*root,*tail,que[maxn],*top[maxn];char ans[maxn];int c[maxn];inline int idx(char c){    return c-'a';}inline void add(int c,int l){    node *p=tail;    node *np=&que[tot++];    np->val=l;    while (p && p->go[c]==NULL) p->go[c]=np,p=p->par;    if (p==NULL) np->par=root;    else    {        node *q=p->go[c];        if (p->val+1==q->val) np->par=q;        else        {            node *nq=&que[tot++];            *nq=*q;            nq->val=p->val+1;            np->par=q->par=nq;            while (p&&p->go[c]==q) p->go[c]=nq,p=p->par;        }    }    tail=np;}inline void init(){    //memset(que,0,sizeof que);    len=1;    tot=0;    root=tail=&que[tot++];}inline void slove(int k){    int now=0;    int l=0;    while (k)    {       for (int i=0; i<cnt[now]; i++)       {           if (k>que[next[now][i]].cnt)           k-=que[next[now][i]].cnt;           else           {               ans[l++]=ch[now][i];               k--;               now=next[now][i];               break;           }       }    }    ans[l]='\0';    puts(ans);}int main(){    //freopen("a.txt","r",stdin);    //freopen("out.txt","w",stdout);    gets(str);    init();    int l=strlen(str);    for (int i=0; i<l; i++)    add(idx(str[i]),len++);   // memset(c,0,sizeof c);   // memset(wtop,0,sizeof wtop);   // memset(cnt,0,sizeof cnt);    for (int i=0; i<tot; i++)    c[que[i].val]++;    for (int i=1; i<len; i++)    c[i]+=c[i-1];    for (int i=0; i<tot; i++)    {        top[--c[que[i].val]]=&que[i];        wtop[c[que[i].val]]=i;    }    for (int i=0; i<tot; i++)    que[i].cnt=1;    for (int i=tot-1; i>=0; i--)    {        node *p=top[i];        for (int j=0; j<S; j++)        {            if (p->go[j])            {                int u=p-que,v=p->go[j]-que;                next[u][cnt[u]]=v;                ch[u][cnt[u]++]=j+'a';                p->cnt+=p->go[j]->cnt;            }        }    }    scanf("%d",&q);    while (q--)    {        scanf("%d",&m);        slove(m);    }    return 0;}


0 0