题目大意

对于一个给定的长度为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;
}

并不对劲的bzoj3998:loj2102:p3975:[TJOI2015]弦论的更多相关文章

  1. Luogu P3975 [TJOI2015]弦论

    题目链接 \(Click\) \(Here\) 题目大意: 重复子串不算的第\(k\)大子串 重复子串计入的第\(k\)大子串 写法:后缀自动机. 和\(OI\) \(Wiki\)上介绍的写法不太一样 ...

  2. 洛谷 P3975 [TJOI2015]弦论 解题报告

    P3975 [TJOI2015]弦论 题目描述 为了提高智商,ZJY开始学习弦论.这一天,她在<String theory>中看到了这样一道问题:对于一个给定的长度为\(n\)的字符串,求 ...

  3. luogu P3975 [TJOI2015]弦论 SAM

    luogu P3975 [TJOI2015]弦论 链接 bzoj 思路 建出sam. 子串算多个的,统计preant tree的子树大小,否则就是大小为1 然后再统计sam的节点能走到多少串. 然后就 ...

  4. P3975 [TJOI2015]弦论

    思路 一眼SAM板子,结果敲了一中午... 我还是太弱了 题目要求求第k小的子串 我们可以把t=0当成t=1的特殊情况,(所有不同位置的相同子串算作一个就是相当于把所有子串的出现位置个数(endpos ...

  5. [洛谷P3975][TJOI2015]弦论

    题目大意:求一个字符串的第$k$大字串,$t$表示长得一样位置不同的字串是否算多个 题解:$SAM$,先求出每个位置可以到达多少个字串($Right$数组),然后在转移图上$DP$,若$t=1$,初始 ...

  6. 【BZOJ3998】[TJOI2015]弦论 后缀自动机

    [BZOJ3998][TJOI2015]弦论 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T ...

  7. bzoj3998: [TJOI2015]弦论(SAM+dfs)

    3998: [TJOI2015]弦论 题目:传送门 题解: SAM的入门题目(很好的复习了SAM并加强Right集合的使用) 其实对于第K小的字符串直接从root开始一通DFS就好,因为son边是直接 ...

  8. BZOJ 3998: [TJOI2015]弦论 [后缀自动机 DP]

    3998: [TJOI2015]弦论 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2152  Solved: 716[Submit][Status] ...

  9. 【BZOJ 3998】 3998: [TJOI2015]弦论 (SAM )

    3998: [TJOI2015]弦论 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2627  Solved: 881 Description 对于一 ...

随机推荐

  1. windows 环境下.Net使用Redis缓存

    Redis简介 Redis是一个开源的,使用C语言编写,面向“键/值”对类型数据的分布式NoSQL数据库系统,特点是高性能,持久存储,适应高并发的应用场景.Redis纯粹为应用而产生,它是一个高性能的 ...

  2. react.js 渲染一个列表的实例

    //引入模块 import React,{Component} from 'react'; import ReactDOM from 'react-dom'; //定义一个要渲染的数组 let use ...

  3. 【HDOJ6319】Ascending Rating(单调队列)

    题意: 思路: 倒着来是因为这样可以维护每一个当过最大值的数,而正着不行 #include<cstdio> #include<cstring> #include<stri ...

  4. 【HDOJ6312】Game(博弈)

    题意: 有一个1到n的序列,两个人轮流取数,取走一个数同时会取走它所有的因子,不能取者为输,两个人都按最优策略取数,问先手是否必胜 思路: #include<cstdio> #includ ...

  5. ThinkPHP5 的入门学习

    与Tp3.2相比,有一下的不同: (1)目录名称的改变: tp3.2的目录命名首字母皆为大写,例如:Application.Public.Controller.Model.View.ThinkPHP. ...

  6. django学习之- Cookie

    cookie:客户端游览器上的一个文件,以键值对进行保存,类似字典{'k':'sfs'},与服务器端没有关系,当游览器访问服务器时候,服务器会生成一个随机字符串保存在cookie中返回给客户端,这样当 ...

  7. poj——3118 Arbiter

      Arbiter 题目描述:      “仲裁者”是<星际争霸>科幻系列中的一种太空船.仲裁者级太空船是神族的战船,专门提供精神力支援.不像其他战船的人员主要是战士阶级,仲裁者所承载的都 ...

  8. Ubuntu 16.04安装SQLite Browser操作SQLite数据库

    安装: sudo apt-get install sqlitebrowser 启动:

  9. foobar2000使用cue文件播放时出现Unable to open item for playback (Object not found):的问题解决

    如下错误: 一般是找不到APE文件导致的.解决方法如下: 1.打开APE文件,对一下路径修改即可.

  10. Excel小tips - 如何设置表格输入数字后末尾自动添加%

    选中一列——鼠标右键——设置单元格格式——数字——自定义——0% 按照以上操作完成后,点击确定,就大功告成了.