bzoj3998 && [TJOI2015]弦论

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3998

题目大意:对于一个给定长度为N的字符串,求它的第K小子串是什么。

题解:后缀自动机

   我们可以这样想:1.从一个节点u开始到v1,v2两点,u,v1,v2在一条路径上,len值大的K值就更大,例如:aab<aabb;

           2.从一个节点u开始到v1分开到v2,v3,那么u-->v1-->v2 && u-->v1---->v3的k值则由v1---v2和v1----v3决定。

           所以我们就可以很容易进行比较大小,利用一下后缀自动机的树状结构,细节见代码。

代码:

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #define maxn 1000005
 7 using namespace std;
 8 char s[maxn];
 9 int T,K;
10 int root,tot,last,m;
11 struct data{
12     int sum[maxn],ssum[maxn],fa[maxn],son[maxn][26],val[maxn],ri[maxn],tmp[maxn],kkd; 
13     int prepare(){last=root=tot=1;}
14     int newnode(int x) {val[++tot]=x; return tot;}
15     void extend(int x)
16     {
17         int p=last,np=newnode(val[p]+1);last=np; ri[np]=1;
18         for (; p && !son[p][x]; p=fa[p]) son[p][x]=np;
19         if (!p) fa[np]=root;
20         else
21         {
22             int q=son[p][x];
23             if (val[q]==val[p]+1) fa[np]=q;
24             else
25             {
26                 int nq=newnode(val[p]+1);
27                 memcpy(son[nq],son[q],sizeof(son[q]));
28                 fa[nq]=fa[q];
29                 fa[q]=fa[np]=nq;
30                 for (; p && son[p][x]==q; p=fa[p]) son[p][x]=nq; 
31             }
32         }
33         
34     }
35     void pre()
36     {
37         for (int i=1; i<=tot; i++) sum[val[i]]++;
38         for (int i=1; i<=tot; i++) sum[i]+=sum[i-1];
39         for (int i=tot; i; i--) tmp[sum[val[i]]--]=i;
40         for (int i=tot; i; i--)
41         {
42             int v=tmp[i];
43             if (T==1) ri[fa[v]]+=ri[v];
44             else ri[v]=1;
45         }
46         ri[1]=0;
47         for (int i=tot; i; i--)
48         {
49             int v=tmp[i]; ssum[v]=ri[v];
50             for (int p=0; p<=25; p++)
51                 ssum[v]+=ssum[son[v][p]];
52         }
53         
54     }
55     void build()
56     {
57         prepare();
58         for (int i=1; i<=m; i++) extend(s[i]-'a');
59     }
60     void dfs(int x,int k)
61     {
62         if (k<=ri[x]) return;
63         k-=ri[x];
64         for (int i=0; i<=25; i++)
65         {
66             if (ssum[son[x][i]]>=k) 
67             {
68                 putchar(i+'a');
69                 dfs(son[x][i],k);
70                 return ;
71             }
72             k-=ssum[son[x][i]];
73         }
74      }
75 }SAM;
76 int main()
77 {
78     scanf("%s",s+1); m=strlen(s+1);
79     scanf("%d%d",&T,&K);
80     SAM.build();
81     SAM.pre();
82     if (K>SAM.ssum[root]) printf("-1");
83     else SAM.dfs(root,K);
84     printf("\n");
85     return 0;
86 }
View Code

开始时间:20:40

结束时间:21:20

posted @ 2016-06-02 08:34  ACist  阅读(256)  评论(0编辑  收藏  举报