洛谷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 ...
随机推荐
- CDH 6.0.1 集群搭建 「Process」
这次搭建我使用的机器 os 是 Centos7.4 RH 系的下面以流的方式纪录搭建过程以及注意事项 Step1: 配置域名相关,因为只有三台机器组集群,所以直接使用了 hosts 的方法: 修改主机 ...
- scrapy几种反反爬策略
一.浏览器代理 1.直接处理: 1.1在setting中配置浏览器的各类代理: user_agent_list=[ "Mozilla/5.0 (Windows NT 10.0; Win64; ...
- tomcat优化实例
———————————————————————————————————— 一.运行模式优化 修改tomcat运行模式为nio<Connector port="80" prot ...
- css多列居中
https://jingyan.baidu.com/article/36d6ed1f67d58f1bcf488393.html
- Nintex Forms Drop-Down "z-index"
Now we’ve got the issue, that if we are working with a “Person-Column”, the drop-down where you can ...
- Js 中一系列宽度和高度的学习
在学习元素一系列宽度和高度之前,我们先来看一个平时开发中几乎不会遇到的问题,那就是html文档声明<!DOCTYPE html> 确实会对元素的宽高产生影响.几乎不会遇到,是因为我们在写h ...
- hdu-1358(kmp)
题意:给你一个长度为n的字符串,问你一共有多少Xi——从0开始到Xi的这段长度这个字符子串是循环串,并输出最多的循环节的次数: 解题思路:用kmp的next数组,我们从next数组的值中可以看出这个字 ...
- 高度可配置的 Linux 内存守护程序 Nohang!
导读 Nohang 是一个 Linux 守护程序,也是一个高度可配置的 OOM(内存溢出)阻止工具,适用于 Linux 系统,能够有效地防止内存不足的情况. 部分功能特性 具有良好注释的配置文件,配置 ...
- Eclipse环境配置与快捷命令
1.VS.Chrome.Eclipse调试命令对比: VS: F5: 继续运行 F10: 单步执行 F11: 进入函数内部 Shift + F11: 由函数内部返回调用处 Chrome: F8: 继续 ...
- Mail.Ru Cup 2018 Round 3
A:签到 #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> # ...