题目大意

对于一个给定的长度为n(\(n\leq5*10^5\))的字符串,

分别求出不同位置的相同子串算作一个、不同位置的相同子串算作多个时,它的第k(\(k\leq10^9\))小子串是什么

题解

建这个字符串的后缀自动机

先dp求出后缀自动机上每一个点能走到多少个字符串

然后从根节点出发,每次走连向dp值不超过k且尽可能大的点的边

代码
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define maxn 500001
#define maxm 1000001
#define int long long
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(int x)
{
if(x==0){putchar('0'),putchar('\n');return;}
int f=0;char ch[20];
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
return;
}
int ch[maxm][26],fa[maxm],rt,lst,cnt,t,n,fir[maxm],nxt[maxm*2],v[maxm*2],cntrd,in[maxm],q[maxm],tl,hd=1,len;
int rgt[maxm],sum[maxm],K;
char s[maxn],ans[maxn];
void ade(int u1,int v1){v[cntrd]=v1,nxt[cntrd]=fir[u1],fir[u1]=cntrd++;}
int gx(char c){return c-'a';}
void ext(int i)
{
int p=lst,np=++cnt,val=gx(s[i]);sum[np]=i,lst=np,rgt[np]=1;
for(;p&&!ch[p][val];p=fa[p])ch[p][val]=np;
if(!p)fa[np]=rt;
else
{
int q=ch[p][val];
if(sum[q]==sum[p]+1)fa[np]=q;
else
{
int nq=++cnt;
sum[nq]=sum[p]+1,fa[nq]=fa[q],fa[q]=fa[np]=nq;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
for(;p&&ch[p][val]==q;p=fa[p])ch[p][val]=nq;
}
}
}
int cmp(int x,int y){return sum[x]<sum[y];}
signed main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
memset(fir,-1,sizeof(fir));
scanf("%s",s+1);lst=rt=++cnt;
t=read(),K=read(),n=strlen(s+1);
rep(i,1,n)ext(i);
rep(i,1,cnt)in[sum[i]]++;
rep(i,1,n)in[i]+=in[i-1];
rep(i,1,cnt)q[in[sum[i]]--]=i;
dwn(i,cnt,1)rgt[fa[q[i]]]+=rgt[q[i]],in[i]=0;
rep(i,1,cnt)
{
rep(j,0,25)if(ch[i][j])in[i]++,ade(ch[i][j],i);
if(in[i]==0)q[++tl]=i;sum[i]=0;
}
if(!t)rep(i,2,cnt)rgt[i]=1;
rgt[rt]=0;
while(hd<=tl)
{
int u=q[hd++];sum[u]+=rgt[u];
for(int k=fir[u];k!=-1;k=nxt[k])
{
sum[v[k]]+=sum[u],in[v[k]]--;
if(in[v[k]]==0)q[++tl]=v[k];
}
}
int u=rt;
while(u&&K>rgt[u])
{
int tmp=rgt[u];int nx=0;
rep(i,0,25)
{
int vv=ch[u][i];
if(vv&&tmp+sum[vv]>=K){ans[++len]=i+'a';nx=1,u=vv,K-=tmp;break;}
tmp+=sum[vv];
}
if(!nx){write(-1);return 0;}
}
printf("%s",ans+1);
return 0;
}

最新文章

  1. C Primer Plus_第9章_函数_编程练习
  2. poj2060Taxi Cab Scheme(二分图匹配)
  3. Android悬浮窗实现 使用WindowManager
  4. PHP实现执行定时任务的几种思路详解
  5. Android中设定EditText的输入长度(转)
  6. ubuntu 装机及装机以后干的事情
  7. 导出含有图片的项目成jar文件后运行,图片不显示
  8. ubuntu 13.10 64bit装BeyondCompare
  9. Tomcat 生产服务器性能优化
  10. 如何选择一个 Linux Tracer (2015)
  11. 关于博客名&ldquo;大话济公&rdquo;的说明
  12. GeoServer基础教程(一):环境搭建篇
  13. 《应用Yii1.1和PHP5进行敏捷Web开发》学习笔记(转)
  14. 十进制字符串转成二进制(decimal to binary)
  15. Light OJ - 1058 Parallelogram Counting(判定平行四边形)
  16. Java项目开发第二天
  17. 打Patch实践
  18. eclipse下classes文件夹无法发布到tomcat的问题--tomcat发布慢的问题
  19. emmet-前端开发神器的几种写法
  20. std::bind学习

热门文章

  1. 服务器端架构及实战 — C#分享
  2. 反编译sencha toucha打包的apk文件,修改应用名称支持中文以及去除应用标题栏
  3. 命令行模式直接下载jar包到本地库
  4. 123. Best Time to Buy and Sell Stock III ~~
  5. wordpress网站后台打开速度很慢解决方法?
  6. 洛谷 P4720 【模板】扩展 / 卢卡斯 模板题
  7. Wannafly挑战赛4
  8. 收集的一些Redis操作技巧教程
  9. 将oracle10g 升级至10.2.0.4
  10. c++多线程编程:常见面试题