link:TJOI2015 弦论

题目大意:

给定一个字符串,输出在对该字符串所有的非空子串排序后第\(k\)个

另外的一个限制是\(T\):子串本质相同但位置不同算\(1\)或多个

\(|s| \leq 5 \times 10^5\)

Solution

“子串排序”,而且数据比较大的时候就要想到后缀自动机了

这个过程有点点像我们在写Treap的时候(就是lyd的书上的代码吧,蒟蒻只学过那一个)

第一步构造一下,套个板子就行

接下来我们先看一下我们的输出代码:

	inline void print(int x,int l)
{
if(l<=val[x]) return ;
l-=val[x];
for(int i=0;i<26;++i)
{
int r=p[x].ch[i]; if(!r) continue;
if(l>sum[r]){l-=sum[r]; continue;}
putchar(i+'a'); print(r,l); return ;
}
}

\(x\)是当前是哪个节点,\(l\)就是还剩下多少的排位

\(val[]\)就是“本质相同串”,有点点类似我们在\(Treap\)上的每一个节点的\(size\)

\(sum[]\)就是子树大小

和\(treap\)找\(rank\)太像了(反正我觉得是)

然后我们的工作就转化成了维护\(sum[]\)的\(val[]\)

看看这段维护代码,一点一点说吧(如果是有学习需要的访客,请跳过这段代码解释,可能有锅)

		for(int i=1;i<=tot;++i) t[len(i)]++;
for(int i=1;i<=tot;++i) t[i]+=t[i-1];
for(int i=1;i<=tot;++i) a[t[len(i)]--]=i;
//上文都是自动机上的操作
//下文就是大力统计“和”
for(int i=tot;i>=1;--i) val[fa(a[i])]+=val[a[i]];
for(int i=1;i<=tot;++i) cas==0?(sum[i]=val[i]=1):(sum[i]=val[i]);
val[1]=sum[1]=0;
for(int i=tot;i>=1;--i)
{
for(int j=0;j<26;++j)
{
if(p[a[i]].ch[j]) sum[a[i]]+=sum[p[a[i]].ch[j]];
}
}

其实到这里我认为是可理解的(博主理解了)

CODE

#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm{
inline int read()
{
int res=0,f=1;char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
const int N=2e6+10;
char s[N];
struct node{
int fa,len,ch[26];
#define fa(x) p[x].fa
#define len(x) p[x].len
}p[N];
int t[N],a[N],sum[N],k,las=1,tot=1,len,cas,val[N];
inline void addp(int x)
{
int tmp=las,np=las=++tot; val[tot]=1; p[np].len=p[tmp].len+1;
for(;tmp&&!p[tmp].ch[x];tmp=p[tmp].fa) p[tmp].ch[x]=np;
if(!tmp) p[np].fa=1;
else
{
int q=p[tmp].ch[x];
if(p[q].len==p[tmp].len+1) p[np].fa=q;
else
{
int nq=++tot;
p[nq]=p[q]; p[nq].len=p[tmp].len+1;
p[q].fa=p[np].fa=nq;
for(;tmp&&p[tmp].ch[x]==q;tmp=p[tmp].fa) p[tmp].ch[x]=nq;
}
} return ;
}
inline void print(int x,int l)
{
if(l<=val[x]) return ;
l-=val[x];
for(int i=0;i<26;++i)
{
int r=p[x].ch[i]; if(!r) continue;
if(l>sum[r]){l-=sum[r]; continue;}
putchar(i+'a'); print(r,l); return ;
}
}
signed main()
{
scanf("%s",s+1); cas=read(); k=read(); len=strlen(s+1);
for(int i=1;i<=len;++i) addp(s[i]-'a');
for(int i=1;i<=tot;++i) t[len(i)]++;
for(int i=1;i<=tot;++i) t[i]+=t[i-1];
for(int i=1;i<=tot;++i) a[t[len(i)]--]=i;
for(int i=tot;i>=1;--i) val[fa(a[i])]+=val[a[i]];
for(int i=1;i<=tot;++i) cas==0?(sum[i]=val[i]=1):(sum[i]=val[i]);
val[1]=sum[1]=0;
for(int i=tot;i>=1;--i)
{
for(int j=0;j<26;++j)
{
if(p[a[i]].ch[j]) sum[a[i]]+=sum[p[a[i]].ch[j]];
}
}
if(sum[1]<k) puts("-1");
else print(1,k),puts("");
return 0;
}
}signed main(){return yspm::main();}

LGOJ3975 TJOI2015 弦论的更多相关文章

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

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

  2. Luogu P3975 [TJOI2015]弦论

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

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

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

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

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

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

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

  6. BZOJ_3998_[TJOI2015]弦论_后缀自动机

    BZOJ_3998_[TJOI2015]弦论_后缀自动机 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行 ...

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

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

  8. luogu P3975 [TJOI2015]弦论 SAM

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

  9. 题解-TJOI2015 弦论

    TJOI2015 弦论 字符串 \(s\) 和 \(t\) 和 \(k\).如果 \(t=0\),不同位置的相同子串算 \(1\) 个:如果 \(t=1\),不同位置的相同子串算多个.求 \(k\) ...

随机推荐

  1. SpringCloud学习之Stream消息驱动【默认通道】(十)

    在实际开发过程中,服务与服务之间通信经常会使用到消息中间件,而以往使用了中间件比如RabbitMQ,那么该中间件和系统的耦合性就会非常高,如果我们要替换为Kafka那么变动会比较大,这时我们可以使用S ...

  2. Java IO流操作(III)——File类&案例一:输出制定目录下所有java文件名(包含子目录)&案例二:删除指定的目录(包含子目录)

    1. File常用的构造 File file = new File("字符串路径"); File f = new File("D:\\a\\b.txt"); F ...

  3. nodejs(15)express开启cors跨域

    express开启cors跨域 package.json "dependencies": { "body-parser": "^1.18.3" ...

  4. import datetime

    import datetimenow = datetime.datetime.now()print('当前时间:',now) 当前时间: 2019-11-21 11:11:58.093122

  5. 吴裕雄--天生自然C++语言学习笔记:C++简介

    C++ 是一种中级语言,它是由 Bjarne Stroustrup 于 年在贝尔实验室开始设计开发的.C++ 进一步扩充和完善了 C 语言,是一种面向对象的程序设计语言.C++ 可运行于多种平台上,如 ...

  6. PAT Advanced 1135 Is It A Red-Black Tree (30) [红⿊树]

    题目 There is a kind of balanced binary search tree named red-black tree in the data structure. It has ...

  7. Physicoochemical|CG content|

    NCBI存在的问题: 数据用户的增长 软件开发受限 数据分析缺乏 有些传统束缚,仅用底层语言书写 Pangenome Open gene是随菌株数量增大而增大的gene,Closed gene是随菌株 ...

  8. Dijkstra与Floyd算法

    1. Dijkstra算法 1.1 定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点 ...

  9. WinServer--mstsc

    部署项目时,远程连接服务器一直提示连接达最大拒绝连接. mstsc /admin 从sp2后,/console参数就改为/admin了,其实就是登陆到远程服务器的控制台,一般加这个参数是为了在远程桌面 ...

  10. Python说文解字_杂谈08

    1. Python变量到底是什么? Python和Java中的变量本质不一样,python的变量实质是一个指针 int str,便利贴 a = 1 # 1. a贴在1上面 # 2. 它的过程是先生成对 ...