[BZOJ3998][TJOI2015]弦论(后缀自动机)
2017-01-01 11:26
459 查看
题目描述
传送门题解
还是要统计每一个点往后走能有多少个不同的子串。如果T=0的时候就是主链上的点都是1,然后在parent树上把儿子加到父亲上去
如果T=1的是候则需要计算每一个点right集合的大小
最后在自动机上暴力找第k小的然后输出即可
代码
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define LL long long #define N 1000005 char s ; int n,T,p,np,q,nq,sz,root,last; int ch [30],pre ,step ,c ,pt ,rt ; LL k,sum ; void extend() { for (int i=0;i<n;++i) { int x=s[i]-'a'; p=last;np=++sz;last=np; step[np]=step[p]+1; while (p&&!ch[p][x]) { ch[p][x]=np; p=pre[p]; } if (!p) pre[np]=root; else { q=ch[p][x]; if (step[q]==step[p]+1) pre[np]=q; else { nq=++sz; step[nq]=step[p]+1; memcpy(ch[nq],ch[q],sizeof(ch[q])); pre[nq]=pre[q]; pre[np]=pre[q]=nq; while (ch[p][x]==q) { ch[p][x]=nq; p=pre[p]; } } } } } void sam() { LL now=0;p=root; while (1) { for (int i=0;i<26;++i) { if (now+sum[ch[p][i]]<k) now+=sum[ch[p][i]]; else { putchar('a'+i); now+=(LL)rt[ch[p][i]]; if (now>=k) return; p=ch[p][i]; break; } } } } int main() { gets(s);n=strlen(s); root=last=++sz; extend(); for (int i=1;i<=sz;++i) ++c[step[i]]; for (int i=1;i<=n;++i) c[i]+=c[i-1]; for (int i=sz;i>=1;--i) pt[c[step[i]]--]=i; scanf("%d%lld",&T,&k); if (!T) { for (int i=1;i<=sz;++i) rt[i]=1; } else { p=root; for (int i=0;i<n;++i) { int x=s[i]-'a'; p=ch[p][x]; rt[p]=1; } for (int i=sz;i>=1;--i) { p=pt[i]; rt[pre[p]]+=rt[p]; } } for (int i=sz;i>=1;--i) { p=pt[i]; if (p!=1) sum[p]=(LL)rt[p]; for (int j=0;j<26;++j) sum[p]+=sum[ch[p][j]]; } if (k>sum[1]) puts("-1"); else sam(); }
相关文章推荐
- 总结下2016年
- 编程语言的发布时间
- Android中怎么彻底销毁一个Dialog
- HDU 1102 Constructing Roads 最小生成树
- iOS微信支付集成全解
- G友年度调查|Do you like me?
- 请教,Android端提交图片文件后,服务器端采用thinkphp该如何接收?
- UVA 11354 Bond(最小生成树+LCA倍增)
- Linux基础学习
- 端游及手游服务端的常用架构
- Clone Graph
- 在Linux系统中修改主机名
- 研究生期间如何从技术菜鸟成长为技术高手
- 求一款能反编译混淆编译apk的软件
- Linux系统值得一看的学习方法及路线图
- 优雅编程之项目开发中的22点编码小建议(三十七)
- 第五章:栅格系统
- UVa 12118 检查员的难题(dfs+欧拉回路)
- 请教有关ListView里的CheckBox选中的问题。
- struts2导入js,css文件无法生效