传送门

题意:

对给定字符串\(s\),求其第\(k\)小子串,重复串被计入以及不被计入这两种情况都需考虑。

思路:

首先构建后缀自动机,之后就考虑在后缀自动机上\(dp\)。

我们知道如果要考虑重复串,那么就会与一个结点的\(endpos\)集合的大小有关,对于一条边\((u,v)\),如果结点\(u\)的\(endpos\)集合大小为\(x\),那么就说明从\(u\)出发到达\(v\),会多出\(x\)种选择。

如果不考虑重复串,直接强制集合大小为\(1\)即可。

之后逆着拓扑序\(dp\)就行,求出从每个结点出发的子串个数。

最后求第\(k\)小的时候,有一些细节需要注意一下,比如从\(u\)到\(v\),\(k\)应该减去\(|endpos(v)|\),因为现在的字符串会有\(|endpos(v)|\)个。

感觉后缀自动机好神奇...好多的性质以及用法...

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 5;
struct node{
int ch[26];
int len, fa;
node(){memset(ch, 0, sizeof(ch)), len = 0;}
}dian[N];
int last = 1, tot = 1;
ll f[N], sum[N];
int n, k, op;
char s[N];
int c[N], a[N];
void add(int c) {
int p = last;
int np = last = ++tot;
dian[np].len = dian[p].len + 1;
f[np] = 1;
for(; p && !dian[p].ch[c]; p = dian[p].fa) dian[p].ch[c] = np;
if(!p) dian[np].fa = 1;
else {
int q = dian[p].ch[c];
if(dian[q].len == dian[p].len + 1) dian[np].fa = q;
else {
int nq = ++tot; dian[nq] = dian[q];
dian[nq].len = dian[p].len + 1;
dian[q].fa = dian[np].fa = nq;
for(; p && dian[p].ch[c] == q; p = dian[p].fa) dian[p].ch[c] = nq;
}
}
}
void dfs(int u) {
if(k <= 0) return;
for(int i = 0; i < 26; i++) {
int v = dian[u].ch[i];
if(k > sum[v]) k -= sum[v];
else {
cout << char(i + 'a');
k -= f[v];
dfs(v);
return;
}
}
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
cin >> s + 1 >> op >> k;
int n = strlen(s + 1);
for(int i = 1; i <= n; i++) add(s[i] - 'a');
for(int i = 1; i <= tot; i++) c[dian[i].len]++;
for(int i = 1; i <= tot; i++) c[i] += c[i - 1];
for(int i = 1; i <= tot; i++) a[c[dian[i].len]--] = i;
for(int i = tot; i; i--) {
if(op) f[dian[a[i]].fa] += f[a[i]];
else f[a[i]] = 1;
}
f[1] = 0;
//长度从大到小,逆着拓扑序
//每个结点的next指针指向的点长度肯定不小于它
for(int i = tot; i >= 1; i--) {
sum[a[i]] = f[a[i]];
for(int j = 0; j < 26; j++) {
int v = dian[a[i]].ch[j];
if(v) sum[a[i]] += sum[v];
}
}
if(sum[1] < k) cout << -1;
else dfs(1);
return 0;
}

[TJOI2015]弦论(后缀自动机)的更多相关文章

  1. 【BZOJ3998】[TJOI2015]弦论 后缀自动机

    [BZOJ3998][TJOI2015]弦论 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T ...

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

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

  3. [bzoj3998][TJOI2015]弦论-后缀自动机

    Brief Description 给定一个字符串, 您需要求出他的严格k小子串或非严格k小子串. Algorithm Design 考察使用后缀自动机. 首先原串建SAM, 然后如果考察每个状态代表 ...

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

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

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

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

  6. 【bzoj3998】[TJOI2015]弦论 后缀自动机+dp

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

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

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

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

    /* 一道在树上乱搞的题目 建立出parent树来, 然后就能搞出每个节点往后能扩展出几个串, 至于位置不同算同一个的话就强制让right集合大小为1即可 然后在树上类比权值线段树找第k大26分统计一 ...

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

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

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

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

随机推荐

  1. MySQL实战45讲学习笔记:第三十讲

    一.复习一下加锁规则 在第20和21篇文章中,我和你介绍了 InnoDB 的间隙锁.next-key lock,以及加锁规则.在这两篇文章的评论区,出现了很多高质量的留言.我觉得通过分析这些问题,可以 ...

  2. [LeetCode] 187. Repeated DNA Sequences 求重复的DNA序列

    All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACG ...

  3. tecplot无法处理高版本fluent导出的Ensight格式

    高版本的Fluent完成计算,将计算结果导出为Ensight格式,然后再导入tecplot当中进行后处理的时候会遇见如下的错误: 但是将低版本的Fluent计算结果导出为Ensight格式,却可以顺利 ...

  4. [HDU4867]Xor (线段树分治+类数位dp)

    [HDU4867]Xor (线段树分治+类数位dp) 提供一种\((m+n) log a log m\)带有常数约\(\frac{1}{log n}\)的算法 处理询问,将后来加入的数算进序列中,则每 ...

  5. 动图+源码,演示 Java 中常用数据结构执行过程及原理

    ​阅读本文大概需要 3.7 分钟. 作者:大道方圆 cnblogs.com/xdecode/p/9321848.html 最近在整理数据结构方面的知识, 系统化看了下Java中常用数据结构, 突发奇想 ...

  6. git生成并添加SSH key

    1.安装Git Bash https://git-scm.com/downloads 2.鼠标右键git bash here 3.执行以下命令: ①   cd ~/.ssh/    [如果没有对应的文 ...

  7. Loj #3045. 「ZJOI2019」开关

    Loj #3045. 「ZJOI2019」开关 题目描述 九条可怜是一个贪玩的女孩子. 这天,她和她的好朋友法海哥哥去玩密室逃脱.在他们面前的是 \(n\) 个开关,开始每个开关都是关闭的状态.要通过 ...

  8. mysql备份、还原数据库(命令行)

    这里记录下MySQL如何通过命令行备份和还原数据库. 简单的三个步骤 方法很简单,可以分为三个步骤: 1.打开cmd控制台(命令行). 2.输入相应命令完成备份还原操作. 3.关闭cmd控制台. 就和 ...

  9. SQLServer之服务器连接

    目录 SQL Server Management Studio连接 CMD命令行窗口连接 通用数据连接文件连接 SQL Server Management Studio连接 定义 SQL Server ...

  10. 解决Laydate在弹出层中一闪而过的问题

    解决办法:添加 trigger: 'click' 属性 laydate.render({ elem: '#demo' ,btns: ['clear', 'now'] ,trigger: 'click' ...