[TJOI2015]弦论
我们先求出该字符串的\(SA\)和\(Ht\)
然后分类讨论
\(T=0\)时,每次去掉\(Ht\)往后扫就行
\(T=1\)时,我们考虑\(lcp\)对答案的影响
既然用到\(lcp\),那就要用\(ST\)表维护
左端点固定时,随右端点的增大,区间\(\min\)单调不升
我们就可以用二分+限制右端点的方式统计某个后缀的前缀的贡献
循环遍历每个后缀时,由于\(Ht\)部分已经统计过对答案的贡献,就不用再计算了,从\(Ht+1\)的位置继续向后统计即可
#include"cstdio"
#include"cstring"
#include"iostream"
#include"algorithm"
using namespace std;
const int MAXN=5e5+5;
int ln,maxn,p,t;
int SA[MAXN],id[MAXN],rnk[MAXN],bnk[MAXN],Ht[MAXN];
char ch[MAXN];
int ST[19][MAXN],lg[MAXN];
void shel()
{
for(int i=1;i<=ln;++i) ++bnk[rnk[id[i]]];
for(int i=1;i<=maxn;++i) bnk[i]+=bnk[i-1];
for(int i=1;i<=ln;++i) SA[++bnk[rnk[id[i]]-1]]=id[i];
for(int i=0;i<=maxn;++i) bnk[i]=0;
return;
}
void GetSA()
{
for(int i=1;i<=ln;++i) rnk[i]=ch[i],id[i]=i,maxn=max(maxn,rnk[i]);
shel();
for(int k=1;k<ln;k<<=1){
for(int i=1;i<=k;++i) id[i]=ln-k+i;
int ct=k;
for(int i=1;i<=ln;++i) if(SA[i]>k) id[++ct]=SA[i]-k;
shel();swap(id,rnk);rnk[SA[1]]=1;
for(int i=2;i<=ln;++i) rnk[SA[i]]=(id[SA[i]]==id[SA[i-1]]&&id[SA[i]+k]==id[SA[i-1]+k])?rnk[SA[i-1]]:rnk[SA[i-1]]+1;
if(rnk[SA[ln]]==ln) return;
maxn=rnk[SA[ln]];
}return;
}
void GetHt()
{
int k=0;
for(int i=1;i<=ln;++i){
if(rnk[i]==1) continue;
if(k) --k;
int ct=SA[rnk[i]-1];
while(ct+k<=ln&&i+k<=ln&&ch[i+k]==ch[ct+k]) ++k;
Ht[rnk[i]]=k;
}return;
}
int Getmi(int l,int r){int tmp=lg[r-l+1];return min(ST[tmp][l+(1<<tmp)-1],ST[tmp][r]);}
void slv1()
{
for(int i=1;i<=ln;++i) lg[i]=i>>lg[i-1]+1?lg[i-1]+1:lg[i-1];
for(int i=1;i<=ln;++i) ST[0][i]=Ht[i];
for(int j=1;j<=lg[ln];++j){
int tmp=1<<j-1;
for(int i=tmp<<1;i<=ln;++i){
ST[j][i]=min(ST[j-1][i],ST[j-1][i-tmp]);
}
}for(int i=1;i<=ln;++i){
int tmp=SA[i]+Ht[i];
int ct=ln;
while(1){
if(tmp>ln) break;
if(ct==i){
if(t>ln-tmp+1){t-=ln-tmp+1;break;}
for(int j=SA[i];j<=tmp+t-1;++j) putchar(ch[j]);
return;
}int l=i,r=ct;
while(l<r){
int mid=l+r+1>>1;
if(Getmi(i+1,mid)>=tmp-SA[i]+1) l=mid;
else r=mid-1;
}ct=r;
if(t>r-i+1) t-=r-i+1;
else{
for(int j=SA[i];j<=tmp;++j) putchar(ch[j]);
return;
}++tmp;
}
}puts("-1");
return;
}
void slv2()
{
int ct=1;
while(t>ln-SA[ct]-Ht[ct]+1) t-=ln-SA[ct]-Ht[ct]+1,++ct;
if(ct>ln){puts("-1");return;}
for(int i=SA[ct];i<=SA[ct]+t+Ht[ct]-1;++i) putchar(ch[i]);
puts("");
return;
}
int main()
{
scanf("%s",ch+1);ln=strlen(ch+1);
GetSA();GetHt();scanf("%d%d",&p,&t);
p?slv1():slv2();
return 0;
}
[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的节点能走到多少串. 然后就 ...
- LGOJ3975 TJOI2015 弦论
link:TJOI2015 弦论 题目大意: 给定一个字符串,输出在对该字符串所有的非空子串排序后第\(k\)个 另外的一个限制是\(T\):子串本质相同但位置不同算\(1\)或多个 \(|s| \l ...
- 题解-TJOI2015 弦论
TJOI2015 弦论 字符串 \(s\) 和 \(t\) 和 \(k\).如果 \(t=0\),不同位置的相同子串算 \(1\) 个:如果 \(t=1\),不同位置的相同子串算多个.求 \(k\) ...
随机推荐
- EF6使用Mysql,踏过的那些坑
在vs2013中使用mysql连接entityFramework经常会遇到这个问题:您的项目引用了最新实体框架:但是,找不到数据连接所需的与版本兼容的实体框架数据提供程序.请退出此向导,安装兼容提供程 ...
- Shell - 简明Shell入门10 - 管道(Pipe)
示例脚本及注释 #!/bin/bash echo '##### Number of *.conf : ' find /etc -name *.conf | grep system | wc -l ec ...
- ES6中的元编程-Proxy & Reflect
前言 ES6已经出来好久了,但是工作中比较常用的只有let const声明,通过箭头函数改this指向,使用promise + async 解决异步编程,还有些数据类型方法...所以单独写一篇文章学习 ...
- python3.6使用f-string来格式化字符串
这里的f-string指的是以f或F修饰的字符串,在字符串中使用{}来替换变量,表达式和支持各种格式的输出.详细的格式化定义可以看官方文档 >>> a, b = 30, 20 > ...
- Node.js对MongoDB进行增删改查操作
MongoDB简介 MongoDB是一个开源的.文档型的NoSQL数据库程序.MongoDB将数据存储在类似JSON的文档中,操作起来更灵活方便.NoSQL数据库中的文档(documents)对应于S ...
- Centos 7 开启BBR
# 升级内核 rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org rpm -Uvh http://www.elrepo.org/elr ...
- dubbo-001--前言
1,前言: 第一次了解dubbo是在15年刚工作的时候在瑞友,项目是给凯撒旅游公司签证部做一个签证系统,项目需要调用一些凯撒的方法,比如权限.部门信息,跟签证相关的一些如签证国家城市.领区啥玩意的,等 ...
- [原创]EF架构随心所欲打造属于你自己的DbModel
前言 我们都知道EF可以生成Dbmodel,系统生成的Model有时候并不是我们想要的,如何我们要生成自己的Model,那么久需要我们手动的去修改T4模版,T4是对“Text Template Tra ...
- rubymine debug需要安装依赖
for ruby2.x gem install ruby-debug-ide --pre gem install debase --pregem install debugger2 --pre
- 05 - JavaSE之数组
一维数组 java中的数组是引用类型,分配在堆空间上. 一维数组的声明方式: type var[]; type[] var; java中声明数组时不能指定其长度,如下,因为java中的数组是分配在堆空 ...