BZOJ 3998: [TJOI2015]弦论 SAM
时间:2019-08-29
本文章向大家介绍BZOJ 3998: [TJOI2015]弦论 SAM,主要包括BZOJ 3998: [TJOI2015]弦论 SAM使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
title
Description
对于一个给定的长度为 \(n\) 的字符串,求出它的第 \(k\) 小子串是什么。
analysis
建出 \(SAM\) 求 \(K\) 大。
\(T=0\) 除了根以外的状态都代表 \(1\) 个串;
\(T=1\) 每个状态 \(fail\) 子树结束结点个数即为串的个数。
code
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+10;
char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
x=0;
T f=1, ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int T,K,n;
struct SuffixAutoMaton
{
int last,cnt;
int ch[maxn<<1][26],fa[maxn<<1],l[maxn<<1];//数据范围不计算清楚真是害死人
inline void extend(int c)
{
int p=last,np=++cnt;
last=cnt;
l[np]=l[p]+1;
for ( ; p && !ch[p][c]; p=fa[p]) ch[p][c]=np;
if (!p) fa[np]=1;
else
{
int q=ch[p][c];
if (l[p]+1==l[q]) fa[np]=q;
else
{
int nq=++cnt;
l[nq]=l[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
for ( ; ch[p][c]==q; p=fa[p]) ch[p][c]=nq;
}
}
siz[np]=1;
}
int c[maxn],a[maxn<<1],siz[maxn<<1],sum[maxn<<1];//数据范围不计算清楚真是害死人
inline void calc()
{
for (int i=1; i<=cnt; ++i) ++c[l[i]];
for (int i=1; i<=n; ++i) c[i]+=c[i-1];//只需要计算出这个字符串实际长度的前缀即可
for (int i=cnt; i; --i) a[c[l[i]]--]=i;//倒序搞
for (int i=cnt; i; --i)//从小到大枚举,实际上在模拟parent树的DFS
{
int p=a[i];
if (T==1) siz[fa[p]]+=siz[p];
else siz[p]=1;
}
siz[1]=0;
for (int i=cnt; i; --i)
{
int p=a[i];
sum[p]=siz[p];
for (int j=0; j<26; ++j) sum[p]+=sum[ch[p][j]];
}
}
inline void dfs(int x,int K)
{
if (K<=siz[x]) return ;
K-=siz[x];
for (int i=0; i<26; ++i)
if (int p=ch[x][i])
{
if (K<=sum[p])
{
putchar(i+'a');
dfs(p,K);
return ;
}
K-=sum[p];
}
}
} SAM;
char s[maxn];
int main()
{
scanf("%s",s+1);
n=strlen(s+1);SAM.cnt=SAM.last=1;//1为跟,表示空串
read(T);read(K);
for (int i=1; i<=n; ++i) SAM.extend(s[i]-'a');
SAM.calc();
if (K>SAM.sum[1]) puts("-1");
else SAM.dfs(1,K),puts("");
return 0;
}
原文地址:https://www.cnblogs.com/G-hsm/p/11427946.html
- nyoj------------找球号(一)
- nyoj------擅长排列的小明
- HDUOJ-------(1211)RSA
- HDUOJ----1301 Jungle Roads
- try语句...
- HDUOJ---1233还是畅通工程
- HDUOJ---1863畅通工程
- HDUOJ---1879 继续畅通工程
- MySQL命令行工具:percona-toolkit安装使用初探
- 解决Nginx配置http2不生效,谷歌浏览器仍然采用http1.1协议问题
- 海量数据切分抽取的实践场景(r11笔记第43天)
- 使用shell自动化诊断性能问题(一)(r11笔记第41天)
- Data Guard实现故障自动切换(二)(r11笔记第40天)
- Oracle Data Guard延迟的原因(r11笔记第69天)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 一天一大 leet(数组中的第 K 个最大元素)难度:中等 DAY-29
- 线程之生产者消费者模式
- Redis学习笔记 -- 2
- 一天一大 leet(单词拆分)难度:中等 DAY-25
- 多线程必考的「生产者 - 消费者」模型,看乔戈里这篇文章就够了
- 一天一大 leet(三角形最小路径和)难度:中等-Day20200715
- 一天一大 leet(将有序数组转换为二叉搜索树)难度:简单-Day20200703
- 一天一大 leet(缺失的第一个正数)难度:困难DAY-27
- 【玩转Redis面试第3讲】一次性将Redis RDB持久化和AOF持久化讲透
- 一天一大 leet(用两个栈实现队列)难度:简单 DAY-30
- SpringBoot实战:整合Redis、mybatis,封装RedisUtils工具类等(附源码)
- 时间序列&日期学习笔记大全(下)
- 带你了解鸿蒙开发基本流程
- Python 中也可以写 Excel 中的 “Vlookup” 函数?太牛逼了吧!
- 一天一大 leet(除数博弈)难度:简单-Day20200724