【题意】给定长度为n的小写字母字符串S,求第k小子串。n<=5*10^5。

给定T,T=0时不同位置的相同子串算一个,T=1时算多个。

【算法】后缀自动机

【题解】对S建立SAM,T=0则每个节点算1次,T=1则每个节点算Right次,那么第k小就是dfs到恰好前k个的位置就是答案(SAM自带字典序)。

DFS前,我们需要每个点的Right数组大小,每个子树(trans边)的Right数组之和。

首先使所有前缀开端节点Right=1(即每次的np),然后对所有点按len进行基数排序从而保证拓扑序,然后从后往前统计。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
struct tree{int len,fa, t[];}t[maxn];
int n,last,T,k,tot,right[maxn],sum[maxn],root,w[maxn],b[maxn];
char s[maxn];
void insert(int c){
int np=++tot;
t[np].len=t[last].len+;
right[np]=;
int x=last;
while(x&&!t[x].t[c])t[x].t[c]=np,x=t[x].fa;
last=np;
if(!x)t[np].fa=root;else{
int y=t[x].t[c];
if(t[y].len==t[x].len+)t[np].fa=y;else{
int nq=++tot;
t[nq]=t[y];
t[nq].len=t[x].len+;
t[nq].fa=t[y].fa;t[y].fa=t[np].fa=nq;
while(x&&t[x].t[c]==y)t[x].t[c]=nq,x=t[x].fa;
}
}
}
void dfs(int x){
if(k<=right[x])return;
k-=right[x];
for(int i=;i<;i++)if(t[x].t[i]){
int y=t[x].t[i];
if(k>sum[y])k-=sum[y];else{
putchar(i+'a');
dfs(y);
return;
}
}
}
int main(){
scanf("%s",s+);n=strlen(s+);
root=tot=last=;
for(int i=;i<=n;i++)insert(s[i]-'a');
scanf("%d%d",&T,&k);
for(int i=;i<=tot;i++)w[t[i].len]++;
for(int i=;i<=n;i++)w[i]+=w[i-];
for(int i=;i<=tot;i++)b[w[t[i].len]--]=i;
for(int j=tot;j>=;j--){
int i=b[j];
if(T)right[t[i].fa]+=right[i];else right[i]=;
}
right[root]=;
for(int o=tot;o>=;o--){
int i=b[o];sum[i]=right[i];
for(int j=;j<;j++)if(t[i].t[j])sum[i]+=sum[t[i].t[j]];
}
if(k>sum[root])printf("-1");else dfs(root);
return ;
}

【BZOJ】3998: [TJOI2015]弦论的更多相关文章

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

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

  2. ●BZOJ 3998 [TJOI2015]弦论

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3998题解: 后缀自动机. 当T=0时, 由于在后缀自动机上沿着trans转移,每个串都是互不 ...

  3. BZOJ 3998: [TJOI2015]弦论 后缀自动机 后缀自动机求第k小子串

    http://www.lydsy.com/JudgeOnline/problem.php?id=3998 后缀自动机应用的一个模板?需要对len进行一个排序之后再统计每个出现的数量,维护的是以该字符串 ...

  4. bzoj 3998 [TJOI2015]弦论——后缀自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3998 相同子串算多个的话,先求好 right ,然后求一个 sm 表示走到这个点之后有几种走 ...

  5. BZOJ 3998 TJOI2015 弦论 后缀自动机+DAG上的dp

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3998 题意概述:对于一个给定长度为N的字符串,求它的第K小子串是什么,T为0则表示不同位置 ...

  6. bzoj 3998: [TJOI2015]弦论【SA+二分||SAM】

    SA的话t==0直接预处理出每个后缀的不同串贡献二分即可,然后t==1就按字典序枚举后缀,然后跳右端点计算和当前后缀的前缀相同的子串个数,直到第k个 不过bzoj上会T #include<ios ...

  7. bzoj 3998: [TJOI2015]弦论

    Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个. ...

  8. BZOJ.3998.[TJOI2015]弦论(后缀自动机)

    题目链接 \(Description\) 给定字符串S,求其第K小子串.(若T=0,不同位置的相同子串算1个:否则算作多个) \(Solution\) 建SAM,处理出对于每个节点,它和它的所有后继包 ...

  9. 【刷题】BZOJ 3998 [TJOI2015]弦论

    Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个. ...

  10. BZOJ 3998 [TJOI2015]弦论 ——后缀自动机

    直接构建后缀自动机. 然后. 然后只需要再后缀自动机的go树上类似二分的方法进行查找即可,实际上是“26分”. 然后遇到了处理right集合的问题,然后觉得在go和parent树上上传都是可以的,毕竟 ...

随机推荐

  1. Iterable,Iterator和forEach

    Iterable Interface Iterable<T> 方法: Iterator<T> iterator() Returns an iterator over a set ...

  2. Java包名命名规则(转载)

    转载自:http://lilinhai548.blog.163.com/blog/static/5847332920155132151359/ 鸣谢原作者  学习Java的童鞋们都知道,Java的包. ...

  3. 《高性能JavaScript》学习笔记——日更中

    ------------------2016-7-20更------------------ 最近在看<高性能JavaScript>一书,里面当中,有讲很多提高js性能的书,正在看的过程中 ...

  4. 对Excle的行和列进行检查 单元格类型转换代码 ;

    对Excle的行和列进行检查  转换代码 : ** * 导入信息 */ @Override public List<Object> add(HttpServletRequest reque ...

  5. Vue.js 判断对象属性是否存,不存在添加

    Vue.set是可以对对象添加属性的,这里item对象添加一个checked属性 //if(typeof item.checked=='undefined'){if(!this.item.checke ...

  6. SQL中INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN区别

    sql中的连接查询有inner join(内连接).left join(左连接).right join(右连接).full join(全连接)四种方式,它们之间其实并没有太大区别,仅仅是查询出来的结果 ...

  7. 【bzoj4027】[HEOI2015]兔子与樱花 树形dp+贪心

    题目描述 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1个树枝连接,我们可以把它 ...

  8. 中小型园区网络的基本部署之动手划分vlan

    在计算机网络中,一个二层网络可以被划分为多个不同的广播域,一个广播域对应了一个特定的用户组,默认情况下这些不同的广播域是相互隔离的.不同的广播域之间想要通信,需要通过一个或多个路由器.这样的一个广播域 ...

  9. linux硬盘满了问题排查

    关键指令: df du find step1: 如果发现硬盘满了,首先要确定一下,使用df查看硬盘使用情况 df -h step2: 从第一步结果判定满了,确定哪些文件或哪个文件占了大头,使用du指令 ...

  10. Alpha 冲刺 —— 十分之二

    队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 协助前端界面的开发 搭建测试用服务器的环境 完成 ...