您的位置:首页 > 其它

BZOJ3998: [TJOI2015]弦论

2016-02-26 21:22 417 查看
一开始想构造后缀树来着后来发现就是SAM上面跑一下就好了

时间感人QAQ

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;

char c;
inline void read(int &a)
{
a=0;do c=getchar();while(c<'0'||c>'9');
while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
}

struct Node
{
Node *last,*ch[30];
bool end;
int len,time,cur;
int ans0,ans2;
Node(){last=NULL;for(len=0;len<=29;len++)ch[len]=NULL;len=0;time=1;ans2=0;}
}*root,*last;
Node *Stack[1000001];
int tot;
inline void add(int data,int place)
{
Node *tp,*ne=new Node;
Stack[++tot]=ne;
ne->time=1;
ne->end=true;
ne->len=last->len+1;
ne->cur=place;
for(tp=last;tp&&!tp->ch[data];tp=tp->last)tp->ch[data]=ne;
if(!tp)
{ne->last=root,last=ne;return;}
else
if(tp->len==tp->ch[data]->len-1)
{ne->last=tp->ch[data];last=ne;return;}
else
{
Node *a=new Node,*b=tp->ch[data];
*a=*b;
a->len=tp->len+1;
a->cur=-1;
Stack[++tot]=a;
a->end=true;
a->time=0;
b->last=ne->last=a;
for(tp;tp&&tp->ch[data]==b;tp=tp->last)
tp->ch[data]=a;
last=ne;
}
}

int h[600001];
int maxn=600000;
Node *S[1000001];
inline void Begin()
{
for(int i=1;i<=tot;i++)
S[i]=Stack[i],h[Stack[i]->len]++;
for(int i=1;i<=maxn;i++) h[i]+=h[i-1];
for(int i=1;i<=tot;i++) Stack[h[S[i]->len]--]=S[i];
while(tot)
{
if(Stack[tot]->last)
Stack[tot]->last->time+=Stack[tot]->time;
Stack[tot]->ans0=Stack[tot]->end?1:0;
Stack[tot]->ans2=Stack[tot]==root?0:Stack[tot]->time;
for(int i=0;i<=29;i++)
if(Stack[tot]->ch[i])
Stack[tot]->ans0+=Stack[tot]->ch[i]->ans0,
Stack[tot]->ans2+=Stack[tot]->ch[i]->ans2;
tot--;
}
}

inline void Ans0(Node *Cur,int k)
{
if(Cur!=root&&k<=1)return;
else if(k>Cur->ans0)
{puts("-1");return ;}
else
{
if(Cur!=root)k--;
for(int i=0;i<=29;i++)
if(Cur->ch[i])
if(k>Cur->ch[i]->ans0)
k-=Cur->ch[i]->ans0;
else
{printf("%c",'a'+i),Ans0(Cur->ch[i],k);return;}
}
}

inline void Ans1(Node *Cur,int k)
{
if(Cur!=root&&k<=Cur->time)return;
else if(k>Cur->ans2)
{puts("-1");return ;}

else
{
if(Cur!=root)k-=Cur->time;
for(int i=0;i<=29;i++)
if(Cur->ch[i])
if(k>Cur->ch[i]->ans2)
k-=Cur->ch[i]->ans2;
else
{printf("%c",'a'+i),Ans1(Cur->ch[i],k);return;}
}
}
char ch[600001];
int main()
{
scanf("%s",ch);
int n=strlen(ch);
int T,K;
root=last=new Node;
Stack[++tot]=root;
root->end=false;
for(int i=1;i<=n;i++)
add(ch[i-1]-'a',i);
Begin();
scanf("%d%d",&T,&K);
T?Ans1(root,K):Ans0(root,K);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: