[TJOI2015]弦论(第k小子串)
题意:
对于一个给定的长度为n的字符串,求出它的第k小子串。
有参数t,t为0则表示不同位置的相同子串算作一个,t为1则表示不同位置的相同子串算作多个。
题解:
首先,因为t的原因,后缀数组较难实现,这里不讨论。
使用后缀自动机:
因为,这里需要按字典序考虑子串,所以要使用trs指针。
首先,计算出每个子串的贡献:t=0则为1,t=1则为出现次数。
然后,通过记搜算出匹配到每个点之后可以形成多少贡献。因为使用trs,无需考虑压缩。
最后,在每个节点处找到唯一一个应当向下计算的点,循环直到找到解。
代码:
#include <stdio.h>
#define ll long long
int trs[1000010][26],fa[1000010],len[1000010],sl=1,la=1;
int su[1000010];ll dp[1000010];
void insert(int c)
{
int np=++sl,p=la;
len[np]=len[la]+1;la=np;
while(p!=0&&trs[p][c]==0)
{
trs[p][c]=np;
p=fa[p];
}
if(p==0)
fa[np]=1;
else
{
int q=trs[p][c];
if(len[q]==len[p]+1)
fa[np]=q;
else
{
int nq=++sl;
len[nq]=len[p]+1;
fa[nq]=fa[q];fa[q]=fa[np]=nq;
for(int i=0;i<26;i++)
trs[nq][i]=trs[q][i];
while(p!=0&&trs[p][c]==q)
{
trs[p][c]=nq;
p=fa[p];
}
}
}
su[la]=1;
}
int fr[1000010],ne[1000010],v[1000010],bs=0;
void addb(int a,int b)
{
v[bs]=b;
ne[bs]=fr[a];
fr[a]=bs++;
}
void build()
{
for(int i=1;i<=sl;i++)
fr[i]=-1;
for(int i=2;i<=sl;i++)
addb(fa[i],i);
}
void dfs0(int u)
{
for(int i=fr[u];i!=-1;i=ne[i])
{
dfs0(v[i]);
su[u]|=su[v[i]];
}
}
void dfs1(int u)
{
for(int i=fr[u];i!=-1;i=ne[i])
{
dfs1(v[i]);
su[u]+=su[v[i]];
}
}
void dfs2(int u)
{
if(dp[u])
return;
dp[u]=su[u];
for(int i=0;i<26;i++)
{
if(trs[u][i])
{
dfs2(trs[u][i]);
dp[u]+=dp[trs[u][i]];
}
}
}
char zf[500010];
int main()
{
int t,k,u=1;
scanf("%s%d%d",zf,&t,&k);
for(int i=0;zf[i]!=0;i++)
insert(zf[i]-'a');
build();
if(t==0)dfs0(1);
else dfs1(1);
dfs2(1);
if(dp[1]-su[1]<k)
{
printf("-1");
return 0;
}
while(1)
{
if(u!=1)
{
if(su[u]>=k)
break;
k-=su[u];
}
int i;
for(i=0;i<26;i++)
{
if(trs[u][i]==0)
continue;
if(dp[trs[u][i]]>=k)
break;
k-=dp[trs[u][i]];
}
printf("%c",i+'a');
u=trs[u][i];
}
return 0;
}
[TJOI2015]弦论(第k小子串)的更多相关文章
- 「BZOJ3998」[TJOI2015] 弦论(第K小子串)
https://www.lydsy.com/JudgeOnline/problem.php?id=3998 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input ...
- HDU 5008 求第k小子串
本题要求第k小的distinct子串,可以根据height数组,二分出这个第k小子串所在后缀的位置信息.由于题目要求子串起始下标尽可能小.所以再在rank数组中,二分出与当前后缀LCP大于等于所求子串 ...
- SPOJ SUBLEX 求第k小子串
题目大意: 对于一个给定字符串,找到其所有不同的子串中排第k小的子串 先构建后缀自动机,然后我们可以将整个后缀自动机看做是一个DAG图,那么我们先进行拓扑排序得到 *b[N] 对于每个节点记录一个sc ...
- Lexicographical Substring Search (spoj7259) (sam(后缀自动机)+第k小子串)
Little Daniel loves to play with strings! He always finds different ways to have fun with strings! K ...
- k小子串 SPOJ - SUBLEX 2
题意: 求字典序第K大的子串 题解: 先求出后缀自动机对应节点 // 该节点后面所形成的自字符串的总数 然后直接模拟即可 #include <set> #include <map&g ...
- BZOJ 3998: [TJOI2015]弦论 后缀自动机 后缀自动机求第k小子串
http://www.lydsy.com/JudgeOnline/problem.php?id=3998 后缀自动机应用的一个模板?需要对len进行一个排序之后再统计每个出现的数量,维护的是以该字符串 ...
- BZOJ3998 弦论 【SAM】k小子串
BZOJ3998 弦论 给一个字符串,问其第\(K\)小字串是什么 两种形式 1.不同起始位置的相同串只算一次 2.不同起始位置的相同串各算一次 首先建\(SAM\) 所有串的数量就是\(SAM\)中 ...
- BZOJ 3998: [TJOI2015]弦论 [后缀自动机 DP]
3998: [TJOI2015]弦论 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2152 Solved: 716[Submit][Status] ...
- 洛谷 P3975 [TJOI2015]弦论 解题报告
P3975 [TJOI2015]弦论 题目描述 为了提高智商,ZJY开始学习弦论.这一天,她在<String theory>中看到了这样一道问题:对于一个给定的长度为\(n\)的字符串,求 ...
随机推荐
- Java调用SqlLoader将大文本导入数据库
Java调用SqlLoader将大文本导入数据库 业务场景:将一千万条数据,大约500M的文本文档的数据导入到数据库 分析:通过Java的IO流解析txt文本文档,拼接动态sql实现insert入库, ...
- C++ 根据两点式方法求直线并求两条直线的交点
Line.h #pragma once //Microsoft Visual Studio 2015 Enterprise //根据两点式方法求直线,并求两条直线的交点 #include"B ...
- python 之 并发编程(生产者消费者模型、守护进程的应用)
9.8 生产者消费者模型 该模型中包含两类重要的角色: 1.生产者:将负责造数据的任务比喻为生产者 2.消费者:接收生产者造出的数据来做进一步的处理的被比喻成消费者 实现生产者消费者模型三要素:1.生 ...
- 修改mysql远程数据库链接密码(转)
原文:https://blog.csdn.net/jianjiao7869/article/details/81029171 原来root用户有两个,一个只允许localhost登陆,一个可运行所有用 ...
- VMWare打开centos,提示内部错误
如题,VMWare打开centos,提示内部错误.该原因是因为服务被停止了之后没有将其启动,将其启动就解决了. CMD客户端输入命令 services.msc 将关于VM的服务启动就可以了
- 表单送件前的Check(二) (未完)
#region 新增表单前的Check动作 public static void NewFormRequestCheck(string _FormID, string _VocaEmpID, stri ...
- 伪静态 net-IIS伪静态配置,使用URLRewriter实现伪静态
https://www.cnblogs.com/zhenzaizai/p/10364343.html 前段时间开发公司官网,用到了URLRewriter实现伪静态,在VS调试模式下没有任何问题,部署到 ...
- 基于【 springBoot +springCloud+vue 项目】一 || 项目架构简介
一.前言 基于前期学习以及工作经验积累,持续更新基于springboot+springcloud+vue的demo项目.
- ScrollView小记
常用代理方法: - (void)scrollViewDidScroll:(UIScrollView *)scrollView 只有 [self.scrolView setContentOffset: ...
- mysql存储过程事务
之前在写一个存储过程的时候由于不仔细导致数据库锁死,这里反省一下. 存储过程是这样的:把数据按顺序插入三张表,如果其中任何一处出错,就把前面已经做了的操作进行回滚,存储过程里面是用事务实现的,我是这么 ...