题目大意

对于一个给定的长度为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. 数据库连接 Mysqli

    //数据库连接 Mysqli $db= new Mysqli("localhost","root","root","asd_808 ...

  2. Android ScaleDrawable

    顾名思义,Android ScaleDrawable实现一个drawable的缩放.写一个例子. 一个线性布局,垂直放几个ImageView,然后依次缩放若干个ScaleDrawable. 布局文件: ...

  3. [HDU4417]Super Mario(主席树+离散化)

    传送门 又是一道主席树模板题,注意数组从0开始,还有主席树耗费空间很大,数组开大点,之前开小了莫名其妙TLE.QAQ ——代码 #include <cstdio> #include < ...

  4. 【Kruscal最小生成树】D. Jungle Roads

    https://www.bnuoj.com/v3/contest_show.php?cid=9154#problem/D [Accepted] #include<iostream> #in ...

  5. CodeForces - 462B Appleman and Card Game

    是一道简单题 将字母从个数多到小排序 然后 再按题目算法得到最多 但是注意 数据类型声明 money要为long long #include <iostream> #include < ...

  6. jQuery根据属性模糊匹配元素

    1.查看带有指定属性的元素: [attribute] 例如: $("div[id]") 2.查看属性值是某个特定值的元素: [attribute=value] 例如: $(&quo ...

  7. oracle alert 日志位置

    Oracle 11g Alert log 文件位置的问题 https://blog.csdn.net/yujin2010good/article/details/7690191 https://blo ...

  8. [Bzoj4521][Cqoi2016]手机号码(数位dp)

    4521: [Cqoi2016]手机号码 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 870  Solved: 505[Submit][Status ...

  9. sql server2008 R2 各个版本的区别与选择

    目前已知的SQL Server 2008 R2的版本有: 企业版.标准版.工作组版.Web版.开发者版.Express版.Compact 3.5版. 这个次序也是各个版本功能的强大程度从高到低的一个排 ...

  10. Activiti-5.3工作流引擎-源码解析(流程文档解析)

    前面我们通过BPMN20.xsd和Activiti自定义的XML Schema文件初步了解了业务流程模型的定义,那么现在我们来了解一下流程文档的解析过程,这个过程主要是通过代码解析来完成. 代码解析过 ...