bzoj3998 && [TJOI2015]弦论

来源:互联网 发布:中国石油库存数据 编辑:程序博客网 时间:2024/06/06 01:46
传送门: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         else21         {22             int q=son[p][x];23             if (val[q]==val[p]+1) fa[np]=q;24             else25             {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

0 0
原创粉丝点击