BZOJ3998 弦论 【SAM】k小子串
BZOJ3998 弦论
给一个字符串,问其第\(K\)小字串是什么
两种形式
1.不同起始位置的相同串只算一次
2.不同起始位置的相同串各算一次
首先建\(SAM\)
所有串的数量就是\(SAM\)中的从起始点开始的路径数量,所以可以先在\(SAM\)上\(dp\)出来从所有节点开始的子串数量,然后递归找就好了
\(dp\)的转移为\(dp[u] = cnt[u] + \sum_{v \in children} dp[v]\)
对于第一种,每个节点的\(cnt\)为\(1\),对于第二种形式,每个节点的\(cnt\)为其\(right\)集合的大小
所以第二种情况下要计算出每个状态的\(right\)集合的大小
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6+7;
typedef long long int LL;
char s[MAXN];
int t,K,n;
struct SAM{
int link[MAXN],len[MAXN],ch[MAXN][26],last,tot;
LL f[MAXN],cnt[MAXN];
vector<int> G[MAXN];
SAM(){ link[0] = -1; last = tot = len[0] = 0; }
void extend(char chr){
int c = chr - 'a';
int np = ++tot, p = last;
cnt[np] = 1; len[np] = len[last] + 1;
while(p!=-1 and !ch[p][c]){
ch[p][c] = np;
p = link[p];
}
if(p==-1) link[np] = 0;
else{
int q = ch[p][c];
if(len[p]+1==len[q]) link[np] = q;
else{
int clone = ++tot;
link[clone] = link[q];
for(int i = 0; i < 26; i++) ch[clone][i] = ch[q][i];
len[clone] = len[p] + 1;
link[q] = link[np] = clone;
while(p!=-1 and ch[p][c]==q){
ch[p][c] = clone;
p = link[p];
}
}
}
last = np;
}
void calsubstring(int u = 0){
f[u] = cnt[u];
for(int c = 0; c < 26; c++){
if(!ch[u][c]) continue;
if(!f[ch[u][c]]) calsubstring(ch[u][c]);
f[u] += f[ch[u][c]];
}
}
void build(){ for(int i = 1; i <= tot; i++) G[link[i]].push_back(i); dfs(0); }
void dfs(int u){
for(int i = 0; i < (int)G[u].size(); i++){
int v = G[u][i];
dfs(v); cnt[u] += cnt[v];
}
}
void _kth(int u, string &str, int k){
if(k<=cnt[u]) return;
k -= cnt[u];
for(int i = 0; i < 26; i++){
if(!ch[u][i]) continue;
if(f[ch[u][i]]>=k){
str.append(1,char(i+'a'));
_kth(ch[u][i],str,k);
return;
}
else k -= f[ch[u][i]];
}
}
string kth(int k){
if(f[0]<k) return string("-1");
string str;
_kth(0,str,k);
return str;
}
}sam;
int main(){
scanf("%s %d %d",s,&t,&K);
n = strlen(s);
for(int i = 0; i < n; i++) sam.extend(s[i]);
if(t==1) sam.build();
else fill(sam.cnt,sam.cnt+MAXN,1);
sam.cnt[0] = 0;
sam.calsubstring();
printf("%s\n",sam.kth(K).c_str());
return 0;
}
BZOJ3998 弦论 【SAM】k小子串的更多相关文章
- 「BZOJ3998」[TJOI2015] 弦论(第K小子串)
https://www.lydsy.com/JudgeOnline/problem.php?id=3998 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input ...
- [TJOI2015]弦论(第k小子串)
题意: 对于一个给定的长度为n的字符串,求出它的第k小子串. 有参数t,t为0则表示不同位置的相同子串算作一个,t为1则表示不同位置的相同子串算作多个. 题解: 首先,因为t的原因,后缀数组较难实现, ...
- HDU 5008 求第k小子串
本题要求第k小的distinct子串,可以根据height数组,二分出这个第k小子串所在后缀的位置信息.由于题目要求子串起始下标尽可能小.所以再在rank数组中,二分出与当前后缀LCP大于等于所求子串 ...
- Lexicographical Substring Search (spoj7259) (sam(后缀自动机)+第k小子串)
Little Daniel loves to play with strings! He always finds different ways to have fun with strings! K ...
- SPOJ SUBLEX 求第k小子串
题目大意: 对于一个给定字符串,找到其所有不同的子串中排第k小的子串 先构建后缀自动机,然后我们可以将整个后缀自动机看做是一个DAG图,那么我们先进行拓扑排序得到 *b[N] 对于每个节点记录一个sc ...
- k小子串 SPOJ - SUBLEX 2
题意: 求字典序第K大的子串 题解: 先求出后缀自动机对应节点 // 该节点后面所形成的自字符串的总数 然后直接模拟即可 #include <set> #include <map&g ...
- BZOJ 3998: [TJOI2015]弦论 后缀自动机 后缀自动机求第k小子串
http://www.lydsy.com/JudgeOnline/problem.php?id=3998 后缀自动机应用的一个模板?需要对len进行一个排序之后再统计每个出现的数量,维护的是以该字符串 ...
- 【BZOJ3998】弦论 [SAM]
弦论 Time Limit: 10 Sec Memory Limit: 256 MB[Submit][Status][Discuss] Description 对于一个给定长度为N的字符串,求它的第 ...
- BZOJ3998:[TJOI2015]弦论(SAM)
Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个. ...
随机推荐
- 利用css和jquery制成弹幕
1.首先上图看下效果 2.废话不多说,直接上代码 1>html代码 <div class="barrage"> <div class="scree ...
- python学习笔记 | strftime()格式化输出时间
time模块 import time t = time.strftime("%Y-%m-%d %H:%M:%S") print(t) datetime模块 import datet ...
- 关于 percona monitoring plugins插件报slave is stoped on ip地址
思路:肯定是某个item触发了触发器 去看触发器,找到 slave is stoped,如下图 看到键是mysql.running-slave ,然后去定义key的文件中查看该键对应的脚本,修改脚本. ...
- 【Java】单例模式(Singleton)
重新搞一波 复习巩固 简单记录 慕课网 Java工程师 文章目录 单例概述 设计模式 单例模式(Singleton) 参考资料 单例概述 Singleton Pattern 单例模式是Java中最简单 ...
- 【Java】面向对象
重新搞一波 复习巩固 简单记录 慕课网 imooc Java 零基础入门-Java面向对象-面向对象 都是视频课件里的. 文章目录 面向对象 什么是对象 什么是面向对象 类 什么是对象的属性和方法 类 ...
- 【linux】系统编程-7-网络编程
目录 前言 10. 网络编程 10.1 简要网络知识 10.2 IP协议 10.2.1 IP地址编址 10.2.2 特殊IP地址 10.2.1 首限广播地址 10.2.2 直接广播地址 10.2.3 ...
- 06--Docker自定义镜像Tomcat9
1. 创建目录 /zhengcj/mydockerfile/tomcat9 2.将jdk和tomcat的安装包拷贝到tomcat9下 3.在tomcat9目录下创建Dockerfile文件,并写以下命 ...
- java 记录数据持续变化时间
1.需求:获取count为null和不为null的持续变化 [{count=0, time=0}, {count=10, time=1000}, {count=20, time=2000}, {cou ...
- 如何在C#中使用MSMQ
MSMQ (Microsoft消息队列)是Windows中默认可用的消息队列.作为跨计算机系统发送和接收消息的可靠方法,MSMQ提供了一个可伸缩.线程安全.简单和使用方便的队列,同时为你提供了在Win ...
- 试玩 GOWOG ,初探 OpenAI(使用 NeuroEvolution 神经进化)与 Golang 多人在线游戏开发
GOWOG: 原项目:https://github.com/giongto35/gowog 我调整过的:https://github.com/Kirk-Wang/gowog GOWOG 是一款迷你的, ...