【BZOJ-3998】弦论 后缀自动机
3998: [TJOI2015]弦论
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 2018 Solved: 662
[Submit][Status][Discuss]
Description
对于一个给定长度为N的字符串,求它的第K小子串是什么。
Input
第一行是一个仅由小写英文字母构成的字符串S
Output
输出仅一行,为一个数字串,为第K小的子串。如果子串数目不足K个,则输出-1
Sample Input
0 3
Sample Output
HINT
N<=5*10^5
Source
Solution
后缀自动机的裸题?不过给我挺大帮助的。
建出后缀自动机求K大的问题,先拓扑排序/基数排序,然后递推出每个节点能到的子串数,然后dfs一遍加加减减。
这个题在递推的时候讨论一下即可,T=0时说明每个状态代表一个子串(除空串以外),T=1时每个节点的Parent树的子树中的节点数都是可以得到的子串数,所以需要累加。
而这个累加的过程,可以理解成是求出$Right$集合的大小,所以构建时的新建节点显然不能重复计算。
然后dfs一遍,类似于线段树上二分的思想,输出答案。
自己没有写递归的写法,直接用的while里非递归。
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define MAXN 500010
char A[MAXN],ans[MAXN];
int N,T,K;
namespace SAM
{
int son[MAXN<<][],par[MAXN<<],len[MAXN<<],root,last,sz,size[MAXN<<];
inline void Init() {root=sz=last=;}
inline void Extend(int c)
{
int cur=++sz,p=last;
len[cur]=len[p]+; size[cur]=;
while (p && !son[p][c]) son[p][c]=cur,p=par[p];
if (!p) par[cur]=root;
else
{
int q=son[p][c];
if (len[p]+==len[q]) par[cur]=q;
else
{
int nq=++sz;
memcpy(son[nq],son[q],sizeof(son[nq])); len[nq]=len[p]+;
par[nq]=par[q];
while (p && son[p][c]==q) son[p][c]=nq,p=par[p];
par[cur]=par[q]=nq;
}
}
last=cur;
}
inline void Build() {Init(); for (int i=; i<=N; i++) Extend(A[i]-'a'+);}
int st[MAXN],id[MAXN<<],sum[MAXN<<];
inline void Pre()
{
for (int i=; i<=sz; i++) st[len[i]]++;
for (int i=; i<=N; i++) st[i]+=st[i-];
for (int i=; i<=sz; i++) id[st[len[i]]--]=i;
if (!T)
{
for (int i=sz; i>=; i--) size[i]=;
size[root]=;
for (int i=sz,Sum=; i>=; i--,Sum=)
{
for (int j=; j<=; j++)
Sum+=sum[son[id[i]][j]];
sum[id[i]]=Sum+;
}
}
else
{
for (int i=sz; i>=; i--)
size[par[id[i]]]+=size[id[i]];
size[root]=;
for (int i=sz; i>=; i--)
{
sum[id[i]]=size[id[i]];
for (int j=; j<=; j++)
sum[id[i]]+=sum[son[id[i]][j]];
}
}
}
inline void Query(int K)
{
int now=root,tot=;
while (K)
{
for (int i=; i<=; i++)
if (son[now][i])
if (sum[son[now][i]]>=K)
{
ans[++tot]='a'+i-;
K-=size[son[now][i]];
now=son[now][i];
break;
}
else K-=sum[son[now][i]]; }
ans[++tot]=;
}
}using namespace SAM;
int main()
{
scanf("%s",A+);
N=strlen(A+);
SAM::Build();
scanf("%d%d",&T,&K);
SAM::Pre();
if (sum[root]<K)
puts("-1");
else
Query(K),puts(ans+);
return ;
}
【BZOJ-3998】弦论 后缀自动机的更多相关文章
- bzoj 3998 弦论 —— 后缀自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3998 关于相同子串算一个还是算多个,其实就是看一种状态的 right 集合是否加上 Pare ...
- BZOJ - 3998 弦论 (后缀自动机)
#include<cstdio> #include<cstring> #include<queue> using namespace std; typedef lo ...
- BZOJ 3998: [TJOI2015]弦论 后缀自动机 后缀自动机求第k小子串
http://www.lydsy.com/JudgeOnline/problem.php?id=3998 后缀自动机应用的一个模板?需要对len进行一个排序之后再统计每个出现的数量,维护的是以该字符串 ...
- BZOJ 3998 TJOI2015 弦论 后缀自动机+DAG上的dp
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3998 题意概述:对于一个给定长度为N的字符串,求它的第K小子串是什么,T为0则表示不同位置 ...
- BZOJ 3998 [TJOI2015]弦论 ——后缀自动机
直接构建后缀自动机. 然后. 然后只需要再后缀自动机的go树上类似二分的方法进行查找即可,实际上是“26分”. 然后遇到了处理right集合的问题,然后觉得在go和parent树上上传都是可以的,毕竟 ...
- 【BZOJ3998】[TJOI2015]弦论 后缀自动机
[BZOJ3998][TJOI2015]弦论 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T ...
- BZOJ 2882: 工艺( 后缀自动机 )
把串S复制成SS然后扔进后缀自动机里, 从根选最小的儿子走, 走N步就是答案了...一开始还想写个treap的...后来觉得太麻烦..就用map了... ----------------------- ...
- [bzoj3998][TJOI2015]弦论-后缀自动机
Brief Description 给定一个字符串, 您需要求出他的严格k小子串或非严格k小子串. Algorithm Design 考察使用后缀自动机. 首先原串建SAM, 然后如果考察每个状态代表 ...
- bzoj 3277 & bzoj 3473,bzoj 2780 —— 广义后缀自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3277 https://www.lydsy.com/JudgeOnline/problem.p ...
随机推荐
- 原型设计Axure的基本使用
Axure是一款专业的原型设计工具, 让负责定义需求设计:功能和界面的人员能快速设计出所需产品,其中不仅包含了对软件产品的界面,交互逻辑的原型设计,还包含了流程图:web网站的线框图,并且能导出说明文 ...
- js操作table表格导出数据到excel方法
js导出excel资料很少,网上也找了很多,基本都不能用,要么只能是IE用,还必须要权限,这是非常不好的.后来到github上找到table2excel.js,虽然可以用,但仍然对IE支持不够,也算不 ...
- 20个不可思议的 WebGL 示例和演示
WebGL 是一项在网页浏览器呈现3D画面的技术,有别于过去需要安装浏览器插件,通过 WebGL 的技术,只需要编写网页代码即可实现3D图像的展示.WebGL 可以为 Canvas 提供硬件3D加速渲 ...
- 使用tomcat manager 管理和部署项目
在部署tomcat项目的时候,除了把war文件直接拷贝到tomcat的webapp目录下,还有一种方法可以浏览器中管理和部署项目,那就是使用tomcat manager. 默认情况下,tomcat m ...
- android MD5加密
public class MD5Uutils { //MD5加密,32位 public static String MD5(String str) { MessageDige ...
- 吐个槽:bose的售后真心差劲!愧对这个顶级音响产品!
400电话只提供周一到周五(中午有1个小时非服务时间),打进去就不厌其烦地告知你服务时间,你多按几个0,对方就直接把电话给你挂了!即使耐心等待它啰嗦完,哪怕只有0个人等待或1个人等待,你也是接不进去的 ...
- Entity Framework之IQueryable和list本地集合
我们来说一下Iqueryable集合和List等本地集合的区别,下面我们通过建立一个简单的例子来学习这个知识点,直接进入主题吧 1.首先对比一下两段代码?看一下有什么结果: (1) 第一段代码如图所示 ...
- yii2 RESTful api的详细使用
作者:白狼 出处:http://www.manks.top/yii2-restful-api.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...
- Win10全屏看视频时任务栏不隐藏
解决办法: 1.对任务栏鼠标右键点击,选择"任务管理器" 2.在进程选项下找到Windows进程中的Windows资源管理器 3.对Windows资源管理器鼠标右键,选择重新启动
- win10用户文件夹重命名,启用administrator账户,删除文件夹时提示找不到该项目
这一切都源自楼主洁癖一般的强迫症. 楼主在重置win10后的安装过程中用microsoft账户登录的电脑,发现用户文件夹名称怪怪的,于是想重命名一下.楼主发现重命名用户文件夹并不能简单地用F2搞定,于 ...