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

    给一个字符串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;
}


你可能感兴趣的:(spoj7258 Lexicographical Substring Search(SUBLEX) 后缀自动机)