LGOJ3975 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 弦论的更多相关文章
- BZOJ 3998: [TJOI2015]弦论 [后缀自动机 DP]
3998: [TJOI2015]弦论 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2152 Solved: 716[Submit][Status] ...
- Luogu P3975 [TJOI2015]弦论
题目链接 \(Click\) \(Here\) 题目大意: 重复子串不算的第\(k\)大子串 重复子串计入的第\(k\)大子串 写法:后缀自动机. 和\(OI\) \(Wiki\)上介绍的写法不太一样 ...
- 洛谷 P3975 [TJOI2015]弦论 解题报告
P3975 [TJOI2015]弦论 题目描述 为了提高智商,ZJY开始学习弦论.这一天,她在<String theory>中看到了这样一道问题:对于一个给定的长度为\(n\)的字符串,求 ...
- 【BZOJ 3998】 3998: [TJOI2015]弦论 (SAM )
3998: [TJOI2015]弦论 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2627 Solved: 881 Description 对于一 ...
- 【BZOJ3998】[TJOI2015]弦论 后缀自动机
[BZOJ3998][TJOI2015]弦论 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T ...
- BZOJ_3998_[TJOI2015]弦论_后缀自动机
BZOJ_3998_[TJOI2015]弦论_后缀自动机 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行 ...
- bzoj3998: [TJOI2015]弦论(SAM+dfs)
3998: [TJOI2015]弦论 题目:传送门 题解: SAM的入门题目(很好的复习了SAM并加强Right集合的使用) 其实对于第K小的字符串直接从root开始一通DFS就好,因为son边是直接 ...
- luogu P3975 [TJOI2015]弦论 SAM
luogu P3975 [TJOI2015]弦论 链接 bzoj 思路 建出sam. 子串算多个的,统计preant tree的子树大小,否则就是大小为1 然后再统计sam的节点能走到多少串. 然后就 ...
- 题解-TJOI2015 弦论
TJOI2015 弦论 字符串 \(s\) 和 \(t\) 和 \(k\).如果 \(t=0\),不同位置的相同子串算 \(1\) 个:如果 \(t=1\),不同位置的相同子串算多个.求 \(k\) ...
随机推荐
- zabbix监控一个机器上的多个java进程的jvm
一.监控安装部署 1.1 JVM端口配置 (/bqhexin/tomcat/bin/catalina.sh)在安装的tomcat路径,找到catalina.sh文件. vim编辑并添加: catali ...
- Python说文解字_杂谈09
1. 元类编程代码分析: import numbers class Field: pass class IntField(Field): # 数据描述符: # 初始化 def __init__(sel ...
- 干货 | DRDS 与TiDB浅析
干货 | DRDS 与TiDB浅析 北京it爷们儿 京东云开发者社区 4月17日 在谈论数据库架构和数据库优化的时候,会常听到"分库分表"."分片".&quo ...
- ssh 账号密码登录设置
找到/etc/ssh/sshd_config文件中的 PasswordAuthentication no 改为PasswordAuthentication yes 并保存. 重启ssh服务:sudo ...
- vue组件使用细节
ref 当ref写在一个标签元素中,通过this.$refs.name 获取的是标签对应的dom元素 <section id="app" ref="froggy&q ...
- 第二季 第四集 part3
obj.insertAdjancetHtlm("beforeend"(位置), r(内容)) insertAdjacentHTML() 将指定的文本解析为HTML或XML,并将结果 ...
- 并发与高并发(八)-线程安全性-原子性-synchronized
前言 闲暇时刻,谈一下曾经在多线程教程中接触的同步锁synchronized,相当于复习一遍吧. 主要介绍 synchronized:依赖JVM Lock:依赖特殊的CPU指令,代码实现,Reetra ...
- Spring MVC中防止csrf攻击
Spring MVC中防止csrf攻击的拦截器示例 https://blog.csdn.net/qq_40754259/article/details/80510088 Spring MVC中的CSR ...
- mybatis的XML配置文件中,typeHandler、jdbcType、javaType的使用
1.前言 typeHandler.jdbcType.javaType都是用来处理java数据类型和jdbc数据库数据类型的转换问题,但在xml的不同位置使用需要注意引号使用问题. 2.在xml的不同位 ...
- Ackermann函数
Ackermann函数定义如下: 若m=0,返回n+1. 若m>0且n=0,返回Ackermann(m-1,1). 若m>0且n>0,返回Ackermann(m-1,Ackerman ...