洛谷P3975 弦论
题意:求一个串的字典序第k小的子串/本质不同第k小的子串。
解:一开始我的想法是在后缀树上找,但是不知道后缀树上的边对应的是哪些字符...
然而可以不用fail树转移,用转移边转移即可。
先建一个后缀自动机,记忆化搜索每个节点向后向后有多少个串。
然后从起点开始向后一个字符一个字符的确定。
注意每到一个新点就要判断是否结束,并把k减去在此结束的串的个数。
#include <cstdio>
#include <cstring> const int N = ; int tr[N][], len[N], fail[N], siz[N], bin[N], cnt[N], topo[N];
int top, last; inline void init() {
top = last = ;
return;
} inline void insert(char c) {
int f = c - 'a';
int p = last, np = ++top;
last = np;
len[np] = len[p] + ;
cnt[np] = ;
while(p && !tr[p][f]) {
tr[p][f] = np;
p = fail[p];
}
if(!p) {
fail[np] = ;
}
else {
int Q = tr[p][f];
if(len[Q] == len[p] + ) {
fail[np] = Q;
}
else {
int nQ = ++top;
len[nQ] = len[p] + ;
fail[nQ] = fail[Q];
fail[Q] = fail[np] = nQ;
memcpy(tr[nQ], tr[Q], sizeof(tr[Q]));
while(tr[p][f] == Q) {
tr[p][f] = nQ;
p = fail[p];
}
}
}
return;
} inline void sort() {
for(int i = ; i <= top; i++) {
bin[len[i]]++;
}
for(int i = ; i <= top; i++) {
bin[i] += bin[i - ];
}
for(int i = ; i <= top; i++) {
topo[bin[len[i]]--] = i;
}
return;
} inline void count() {
for(int i = top; i >= ; i--) {
int x = topo[i];
cnt[fail[x]] += cnt[x];
}
return;
} char s[N]; int DFS(int x) {
if(siz[x]) {
return siz[x];
}
siz[x] = cnt[x];
for(int i = ; i < ; i++) {
if(tr[x][i]) {
siz[x] += DFS(tr[x][i]);
}
}
return siz[x];
} int main() {
scanf("%s", s + );
int n = strlen(s + );
init();
for(int i = ; i <= n; i++) {
insert(s[i]);
}
sort();
int flag, k;
scanf("%d%d", &flag, &k);
if(flag) {
count();
}
else {
for(int i = ; i <= top; i++) {
cnt[i] = ;
}
} int sum = ;
for(int i = ; i <= top; i++) {
sum += cnt[i] * (len[i] - len[fail[i]]);
} int p = ;
DFS(p);
if(k > sum) {
puts("-1");
return ;
}
cnt[] = ;
while() {
//printf("k = %d %d \n", k, k == 1);
if(k == ) {
break;
}
else {
k -= cnt[p];
}
//printf("k = %d p = %d \n", k, p);
for(int i = ; i < ; i++) {
if(!tr[p][i]) {
continue;
}
if(siz[tr[p][i]] >= k) {
putchar(i + 'a');
p = tr[p][i];
break;
}
else {
k -= siz[tr[p][i]];
}
}
} return ;
}
AC代码
又思考了一下,虽然记忆化搜索会搜到重复的节点,但是这些重复所表示的是到达它的不同方案,也就是它代表的不同子串。所以需要重复统计。
这样一个节点的一条转移边其实就是它下一个字符拼上f之后能形成的子串数。
感觉好神奇...
洛谷P3975 弦论的更多相关文章
- 洛谷 P3975 [TJOI2015]弦论 解题报告
P3975 [TJOI2015]弦论 题目描述 为了提高智商,ZJY开始学习弦论.这一天,她在<String theory>中看到了这样一道问题:对于一个给定的长度为\(n\)的字符串,求 ...
- 洛谷 P3975 / loj 2102 [TJOI2015] 弦论 题解【后缀自动机】【拓扑排序】
后缀自动机入门. 题目描述 为了提高智商,ZJY 开始学习弦论. 这一天,她在<String theory>中看到了这样一道问题:对于一个给定的长度为 \(n\) 的字符串,求出它的第 \ ...
- [洛谷P3975][TJOI2015]弦论
题目大意:求一个字符串的第$k$大字串,$t$表示长得一样位置不同的字串是否算多个 题解:$SAM$,先求出每个位置可以到达多少个字串($Right$数组),然后在转移图上$DP$,若$t=1$,初始 ...
- 【洛谷 P3975】 [TJOI2015]弦论(后缀自动机)
题目链接 建出后缀自动机. T=0,每个子串算一次,否则每个子串算该子串的\(endpos\)集合大小次. 用\(f[i]\)表示结点\(i\)表示的\(endpos\)集合大小,则\(f[i]\)为 ...
- 洛谷P3975 跳房子 [DP,单调队列优化,二分答案]
题目传送门 跳房子 题目描述 跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一. 跳房子的游戏规则如下: 在地面上确定一个起点,然后在起点右侧画 n 个格子,这些格子都在同一 ...
- 洛谷1640 bzoj1854游戏 匈牙利就是又短又快
bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...
- 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.
没有上司的舞会 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...
- 洛谷P1108 低价购买[DP | LIS方案数]
题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...
- 洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn Label:二维数组前缀和 你够了 这次我用DP
题目背景 (USACO 5.3.4) 题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚.他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方.我们假定,他的农场划分成 N ...
随机推荐
- js中怎么使点击按钮后文本框获得焦点
<html> <head> <script type="text/javascript"> function setFocus() { docu ...
- 学习 Spring (十五) Advisor
Spring入门篇 学习笔记 advisor 就像一个小的自包含的方面,只有一个 advice 切面自身通过一个 bean 表示,并且必须实现某个 advice 接口,同时 advisor 也可以很好 ...
- BZOJ 1800 [Ahoi2009]fly 飞行棋
题目链接 思路 终于有一道自己想出来的题了,开心. 因为是矩形,一定有直角,所以考虑直径,之后由于矩形对角线是两条直径,所以考虑组合数. 直径有n条,矩形有c(n,2)个. #include<i ...
- Django通用视图APIView和视图集ViewSet的介绍和使用
原 Django通用视图APIView和视图集ViewSet的介绍和使用 2018年10月21日 14:42:14 不睡觉假扮古尔丹 阅读数:630 1.APIView DRF框架的视图的基类是 ...
- h5 打开 app
目前只支持在浏览器中打开,如果非浏览器,例如 微信 支付宝 钉钉 第三方 app 中会弹出下载页面 schemeUrl 为 和app 约定url openApp() { /* 小希学生端 aoji ...
- 一条命令停止所有lxc容器,删除所有lxc容器
for i in $(virsh -c lxc:/// list | grep -v 'Id' | awk '{print $2}');do virsh -c lxc:/// destroy ${i} ...
- wpgwhpg
//f[i][j]就是第is时wpgwhpg的疲劳度是j,那么我们就可以就ta这1s是否休息进行讨论 #include<bits/stdc++.h> using namespace std ...
- springboot 简单搭建
springboot的入门请参考:https://blog.csdn.net/hanjun0612/article/details/81538449 这里就简单看下搭建: 一,看一下项目结构: 创建一 ...
- 微信web开发者工具 移动调试
1 下载 微信web开发者工具:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455784140 下载一个自己能用的版本: 2 ...
- P1140 相似基因 最长公共子序列
思路 类似于最长公共子序列 把一段基因和另外一段基因匹配 不够长的用空基因替换 #include<bits/stdc++.h> using namespace std; const in ...