Luogu P3975 [TJOI2015]弦论
[题目链接 \(Click\) \(Here\)](P3975 [TJOI2015]弦论)
题目大意:
重复子串不算的第\(k\)大子串
重复子串计入的第\(k\)大子串
写法:后缀自动机。
和\(OI\) \(Wiki\)上介绍的写法不太一样,因为要同时解决两个问题。
把字符串每个前缀所在等价类的\(siz\)记为\(1\),然后在\(parent\) \(tree\)上跑一次统计,就可以求出来每一个等价类在串中出现的次数。这里采用类似后缀排序的方法,对字符串按\(len\)为关键字进行排序。至于经过每个点的路径数\(sum\),可以在\(Trie\)边上对后面节点的\(sum\)(=每一个等价类在串中出现次数)求和得到(初始值等于\(siz\),因为每个点还有不选的情况)。
不要忘了把\(siz[1]\)和\(sum[1]\)清空!
#include <bits/stdc++.h>
using namespace std;
const int N = 1100010;
char s[N];
int las = 1, node = 1;
int fa[N], len[N], siz[N], ch[N][26];
void extend (int c) {
register int p, q, x, y;
p = las, q = ++node; las = q;
len[q] = len[p] + 1; siz[q] = 1;
while (p != 0 && ch[p][c] == 0) {
ch[p][c] = q;
p = fa[p];
}
if (p == 0) {
fa[q] = 1;
} else {
x = ch[p][c];
if (len[x] == len[p] + 1) {
fa[q] = x;
} else {
y = ++node;
fa[y] = fa[x];
fa[x] = fa[q] = y;
len[y] = len[p] + 1;
memcpy (ch[y], ch[x], sizeof (ch[x]));
while (p != 0 && ch[p][c] == x) {
ch[p][c] = y;
p = fa[p];
}
}
}
}
int t, k, nd[N], bin[N]; long long sum[N];
void output (int u) {
if (k <= siz[u]) return;
k -= siz[u];
register int i;
for (i = 0; i < 26; ++i) {
if (ch[u][i]) {
if (k > sum[ch[u][i]]) {
k -= sum[ch[u][i]];
} else {
printf ("%c", i + 'a');
output (ch[u][i]);
return;
}
}
}
}
int main () {
scanf ("%s %d %d", s, &t, &k);
register int i, j, n;
n = strlen (s);
for (i = 0; i < n; ++i) extend (s[i] - 'a');
for (i = 1; i <= node; ++i) bin[len[i]]++;
for (i = 1; i <= node; ++i) bin[i] += bin[i - 1];
for (i = 1; i <= node; ++i) nd[bin[len[i]]--] = i;
for (i = node; i >= 1; --i) siz[fa[nd[i]]] += siz[nd[i]];
for (i = 1; i <= node; ++i) t == 0 ? (sum[i] = siz[i] = 1) : (sum[i] = siz[i]);
siz[1] = sum[1] = 0;
for (i = node; i >= 1; --i) {
for (j = 0; j < 26; ++j) {
if (ch[nd[i]][j]) {
sum[nd[i]] += sum[ch[nd[i]][j]];
}
}
}
if (sum[1] < k) {
puts ("-1");
} else {
output (1);
}
}
\(p.s\)关于后缀数组求第一问的方法:
枚举每一个后缀,第i个后缀对答案的贡献为\(len−sa[i]+1−height[i]\)。
Luogu P3975 [TJOI2015]弦论的更多相关文章
- luogu P3975 [TJOI2015]弦论 SAM
luogu P3975 [TJOI2015]弦论 链接 bzoj 思路 建出sam. 子串算多个的,统计preant tree的子树大小,否则就是大小为1 然后再统计sam的节点能走到多少串. 然后就 ...
- 洛谷 P3975 [TJOI2015]弦论 解题报告
P3975 [TJOI2015]弦论 题目描述 为了提高智商,ZJY开始学习弦论.这一天,她在<String theory>中看到了这样一道问题:对于一个给定的长度为\(n\)的字符串,求 ...
- P3975 [TJOI2015]弦论
思路 一眼SAM板子,结果敲了一中午... 我还是太弱了 题目要求求第k小的子串 我们可以把t=0当成t=1的特殊情况,(所有不同位置的相同子串算作一个就是相当于把所有子串的出现位置个数(endpos ...
- [洛谷P3975][TJOI2015]弦论
题目大意:求一个字符串的第$k$大字串,$t$表示长得一样位置不同的字串是否算多个 题解:$SAM$,先求出每个位置可以到达多少个字串($Right$数组),然后在转移图上$DP$,若$t=1$,初始 ...
- 并不对劲的bzoj3998:loj2102:p3975:[TJOI2015]弦论
题目大意 对于一个给定的长度为n(\(n\leq5*10^5\))的字符串, 分别求出不同位置的相同子串算作一个.不同位置的相同子串算作多个时,它的第k(\(k\leq10^9\))小子串是什么 题解 ...
- BZOJ 3998: [TJOI2015]弦论 [后缀自动机 DP]
3998: [TJOI2015]弦论 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2152 Solved: 716[Submit][Status] ...
- 【BZOJ 3998】 3998: [TJOI2015]弦论 (SAM )
3998: [TJOI2015]弦论 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2627 Solved: 881 Description 对于一 ...
- [Luogu 3973] TJOI2015 线性代数
[Luogu 3973] TJOI2015 线性代数 这竟然是一道最小割模型. 据说是最大权闭合子图. 先把矩阵式子推出来. 然后,套路建模就好. #include <algorithm> ...
- 【BZOJ3998】[TJOI2015]弦论 后缀自动机
[BZOJ3998][TJOI2015]弦论 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T ...
随机推荐
- Windows 10 安装PHP Manager 失败的解决办法
首先安装.NET 2.0和.NET 3.5, 在 控制面板----程序----启用或关闭Windows功能 里面 然后修改注册表:HKLM/System/CCS/Services/W3SVC/P ...
- faster rcnn训练详解
http://blog.csdn.net/zy1034092330/article/details/62044941 py-faster-rcnn训练自己的数据:流程很详细并附代码 https://h ...
- codeforces29A
Spit Problem CodeForces - 29A In a Berland's zoo there is an enclosure with camels. It is known that ...
- RMQ--ST表
RMQ即区间最值查询,是指这样一个问题:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j之间的最小/大值. ST表既ST算法是一个非常有名的在线处 ...
- 「NOI2003」逃学的小孩
传送门:>HERE< 题意:给出一棵树(带权),要从一个节点C先走到距离它近的一个节点B,再走到A,要求最坏情况下的总路程(即最长). 解题思路: 乍一看,A,B,C都没给出,这怎么求? ...
- FPGA中亚稳态相关问题及跨时钟域处理
前言 触发器输入端口的数据在时间窗口内发生变化,会导致时序违例.触发器的输出在一段时间内徘徊在一个中间电平,既不是0也不是1.这段时间称为决断时间(resolution time).经过resolut ...
- Codeforces Round #540 (Div. 3) A,B,C,D2,E,F1
A. Water Buying 链接:http://codeforces.com/contest/1118/problem/A 实现代码: #include<bits/stdc++.h> ...
- Linux block(1k) block(4k) 换算 gb
输入 df 显示1k blocks 大小 再输入 df -h 显示 gb换算大小 结论 block(1k) 计算公式为: block(1k) /1024/1000 = xx gb ...
- python学习日记(函数--装饰器)
楔子 前提,我有一段代码(一个函数). import time def run_time(): time.sleep(0.1) print('我曾踏足山巅') 需求1:现在,我想计算这段代码的运行时间 ...
- NOIp 2018 游记
Day0 啥都没做,记了一下 vimrc 和配置,然后搞了一下午的颓. 然后头有点晕乎乎的,早点洗澡去睡觉,在床上想了很多,但还是强制自己大脑放空,早点睡着了. Day1 由于去年的教训,今年我决定先 ...