题目:http://www.spoj.com/problems/SUBLEX/
题意:给一个字符串,然后给Q个询问,每个询问输入一个数K,输出子串中字典序为K的字符串。
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
const int N=250005;
struct State
{
State *pre,*go[26];
int step,v;
void clear()
{
v=0;
pre=0;
step=0;
memset(go,0,sizeof(go));
}
}*root,*last;
State statePool[N*2],*b[2*N],*cur;
void init()
{
cur=statePool;
root=last=cur++;
root->clear();
}
void Insert(int w)
{
State *p=last;
State *np=cur++;
np->clear();
np->step=p->step+1;
while(p&&!p->go[w])
p->go[w]=np,p=p->pre;
if(p==0)
np->pre=root;
else
{
State *q=p->go[w];
if(p->step+1==q->step)
np->pre=q;
else
{
State *nq=cur++;
nq->clear();
memcpy(nq->go,q->go,sizeof(q->go));
nq->step=p->step+1;
nq->pre=q->pre;
q->pre=nq;
np->pre=nq;
while(p&&p->go[w]==q)
p->go[w]=nq, p=p->pre;
}
}
last=np;
}
char str[N];
int son[2*N][26];
char ch[2*N][26];
int cnt[2*N],c[2*N];
void Solve(int k)
{
int ct=0;
int now=0;
while(k)
{
for(int i=0; i<c[now]; i++)
{
State *tmp=statePool+son[now][i];
if(k>tmp->v)
k-=tmp->v;
else
{
str[ct++]=ch[now][i];
now=son[now][i];
k--;
break;
}
}
}
str[ct]=0;
puts(str);
}
int main()
{
int n;
scanf("%s",str);
n=strlen(str);
init();
for(int i=0; i<n; i++)
Insert(str[i]-'a');
memset(cnt,0,sizeof(cnt));
memset(c,0,sizeof(c));
for(State *p=statePool; p!=cur; p++)
cnt[p->step]++;
for(int i=1; i<cur-statePool; i++)
cnt[i]+=cnt[i-1];
for(State *p=statePool; p!=cur; p++)
b[--cnt[p->step]]=p;
for(State *p=statePool; p!=cur; p++)
p->v=1;
int num=cur-statePool;
for(int i=num-1; i>=0; i--)
{
State *p=b[i];
for(int j=0; j<26; j++)
{
if(p->go[j])
{
int x=p-statePool;
int y=p->go[j]-statePool;
son[x][c[x]]=y;
ch[x][c[x]++]=j+'a';
p->v+=p->go[j]->v;
}
}
}
int Q,k;
scanf("%d",&Q);
while(Q--)
{
scanf("%d",&k);
Solve(k);
}
return 0;
}