bzoj3998 [TJOI2015]弦论

后缀自动机

我们建出后缀自动机,对于每个节点我们算出他和他的后继结点一共可以形成多少个不同的串,不同根据t来定义

这里我们不需要考虑每个节点代表的那些等价类字符串,因为那些字符串不同的前缀在到达这个节点前已经确定了,所以我们只需要在t=1时一下考虑right集合的大小,right集合的大小需要在parent树上pushup,乱搞一下就好了。

最后dfs一下即可。

发现bzoj榜上的时间都很接近,于是就在Troywar的帮助下卡了波常,然而只到了第一页,并没有快多少。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #define N 1000500
 7 using namespace std;
 8 int n,m,o;
 9 char s[N>>1];
10 int last,tot,mx[N],par[N],ch[N][26];
11 int val[N],sum[N],buc[N],q[N];
12 void add(int c){
13     int p=last,np=++tot;
14     mx[np]=mx[p]+1;val[np]=1;
15     for(;p&&!ch[p][c];p=par[p])ch[p][c]=np;
16     if(!p)  par[np]=1;
17     else{
18         int q=ch[p][c];
19         if(mx[q]==mx[p]+1)par[np]=q;
20         else{
21             int nq=++tot;
22             mx[nq]=mx[p]+1;
23             par[nq]=par[q];
24             memcpy(ch[nq],ch[q],sizeof ch[nq]);
25             par[q]=par[np]=nq;
26             for(;p&&ch[p][c]==q;p=par[p])ch[p][c]=nq;
27         }
28     }last=np;
29 }
30 void init(){
31     for(int i=1;i<=tot;i++)buc[mx[i]]++;
32     for(int i=1;i<=n;i++)buc[i]+=buc[i-1];
33     for(int i=tot;i;i--)q[buc[mx[i]]--]=i;
34     for(int i=tot;i;i--){
35         if(!o)val[q[i]]=1;
36         else val[par[q[i]]]+=val[q[i]];
37     }val[1]=0;
38     for(int i=tot;i;i--){
39         sum[q[i]]=val[q[i]];
40         for(int j=0;j<26;j++)
41             sum[q[i]]+=sum[ch[q[i]][j]];
42     }
43 }
44 void dfs(int x,int k){
45     if(k<=val[x])return ;
46     k-=val[x];
47     for(int i=0;i<26;i++)if(ch[x][i]){
48         if(sum[ch[x][i]]>=k){
49             putchar(i+'a');
50             dfs(ch[x][i],k);
51             return ;
52         }k-=sum[ch[x][i]];
53     }
54 }
55 int main(){
56     last=++tot;
57     scanf("%s",s+1);
58     n=strlen(s+1);
59     for(int i=1;i<=n;i++)add(s[i]-'a');
60     scanf("%d%d",&o,&m);
61     init();
62     if(m>sum[1])puts("-1");
63     else dfs(1,m);
64 }
View Code

 

posted @ 2018-01-28 15:38  Ren_Ivan  阅读(150)  评论(0编辑  收藏  举报