又领悟到了一点新的东西,后缀自动机其实可以分为两个数据结构,一个是后缀树,还有一个是自动机

后缀树用来划分endpos集合,并且维护后缀之间的关系,此时每个结点代表的是一些后缀相同且长度连续的子串

自动机用来处理边的转移,或者用来解决串的匹配问题,此时每个结点代表的只是一个串,这个串等于从root开始到这结点经过的路径,由于路径可能有很多条,所以对应到后缀树上,就是有一段连续的串啦

字典序第k小的串刚好可以用SAM的性质解决

/*
题目要求考虑两种情况:
首先来考虑算重复子串的情况
处理后缀树:先求出每个状态endpos的大小(即这个状态代表的所有串出现的次数)size[i](endpos的大小即该状态的后缀子树的大小,所有的前缀结点贡献为1,克隆结点大小为0)
处理自动机:自底向上求出从每个状态出发能形成的子串个数 sum[i]+=sum{sum[j]} ,初始有sum[i]=size[i](即从这种状态开始有多少不同的子串,当然这种状态本身的方案数也算)
最后以root为起点,在自动机上进行搜索即可,具体搜索方式类似于多叉树(DAG)查询
然后来考虑不算重复子串的情况
处理后缀树:求endpos的大小
处理自动机:自底向上求每个状态出发能形成的子串个数sum[i]=sum{sum[j]} 初始有sum[i]=1,即这个状态的每个串认为只出现一次
再换一种思路:其实只要维护处每个状态作为起点的不同路径数即可
搜索过程不变
*/
#include<bits/stdc++.h>
using namespace std;
#define maxn 500005
long long T,K;
char s[maxn];
struct SAM{
int last,cnt;
int nxt[maxn<<][];
int len[maxn<<];
int link[maxn<<];
int size[maxn<<];
long long sum[maxn<<];//sum[i]表示从状态i开始的子串总数
SAM(){
last=cnt=;
}
void add(int c){
int p=last,np=last=++cnt;
len[np]=len[p]+;
size[np]=;
for(;p&&!nxt[p][c];p=link[p])
nxt[p][c]=np;
if(!p){link[np]=;return;} int q=nxt[p][c];
if(len[q]==len[p]+){link[np]=q;return;} int clone=++cnt;
link[clone]=link[q];
len[clone]=len[p]+;
memcpy(nxt[clone],nxt[q],sizeof nxt[q]);
link[q]=link[np]=clone;
for(;p&&nxt[p][c]==q;p=link[p])
nxt[p][c]=clone;
}
int id[maxn<<],t[maxn<<];
void sort(){
for(int i=;i<=cnt;i++)t[len[i]]++;
for(int i=;i<=cnt;i++)t[i]+=t[i-];
for(int i=;i<=cnt;i++)id[t[len[i]]--]=i;
}
void work(){//求子串的总数
//处理后缀树上的endpos
for(int i=cnt;i>=;i--)
size[link[id[i]]]+=size[id[i]];
for(int i=;i<=cnt;i++)
if(T==)sum[i]=size[i]=;//要求去重,每个状态代表的串只统计一次
else sum[i]=size[i];
size[]=sum[]=;
//自底向上处理自动机
for(int i=cnt;i>=;i--)
for(int j=;j<;j++)
if(nxt[id[i]][j])
sum[id[i]]+=sum[nxt[id[i]][j]];
}
}p; void print(long long now,long long k){
if(k<=p.size[now])return;//如果这个结点代表的串也不能走完,返回
k-=p.size[now];
for(int i=;i<;i++){
int tmp=p.nxt[now][i];
if(!tmp)continue;
if(k>p.sum[tmp]){
k-=p.sum[tmp];
continue;
} putchar(i+'a');//沿着这个状态往下搜
print(tmp,k);
return;
}
} int main(){
scanf("%s%lld%lld",s,&T,&K);
int len=strlen(s);
for(int i=;i<len;i++)
p.add(s[i]-'a'); p.sort(); p.work(); if(p.sum[]<K)printf("-1");
else print(,K);
puts(""); }

后缀自动机求字典序第k小的串——p3975的更多相关文章

  1. hdu 5008 查找字典序第k小的子串

    Boring String Problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Ot ...

  2. Leetcode 440.字典序第k小的数字

    字典序第k小的数字 给定整数 n 和 k,找到 1 到 n 中字典序第 k 小的数字. 注意:1 ≤ k ≤ n ≤ 109. 示例 : 输入: n: 13 k: 2 输出: 10 解释: 字典序的排 ...

  3. BZOJ 3998: [TJOI2015]弦论 后缀自动机 后缀自动机求第k小子串

    http://www.lydsy.com/JudgeOnline/problem.php?id=3998 后缀自动机应用的一个模板?需要对len进行一个排序之后再统计每个出现的数量,维护的是以该字符串 ...

  4. Alice's Classified Message HDU - 5558 后缀自动机求某个后缀出现的最早位置

    题意: 给定一个长度不超过 10W 的只包含小写字母的字符串,从下标 0 到 n−1.从下标 0 开始操作, 每次对于下标 pos查找下标 pos 开始的子串中最长的在其他地方出现过的长度,其他出现的 ...

  5. str2int HDU - 4436 后缀自动机求子串信息

    题意: 给出 n 个串,求出这 n 个串所有子串代表的数字的和. 题解; 首先可以把这些串构建后缀自动机(sam.last=1就好了), 因为后缀自动机上从 root走到的任意节点都是一个子串,所有可 ...

  6. SPOJ COT Count on a tree(树上主席树 + LCA 求点第k小)题解

    题意:n个点的树,每个点有权值,问你u~v路径第k小的点的权值是? 思路: 树上主席树就是每个点建一棵权值线段树,具体看JQ博客,LCA用倍增logn求出,具体原理看这里 树上主席树我每个点的存的是点 ...

  7. poj2886(线段树求序列第k小)

    题目链接:https://vjudge.net/problem/POJ-2886 题意:n个人围成一个圈,每个人有姓名s和权值val两个属性,第一轮序号为k的人退出,并根据其val指定下一个人,val ...

  8. poj2182(线段树求序列第k小)

    题目链接:https://vjudge.net/problem/POJ-2182 题意:有n头牛,从1..n编号,乱序排成一列,给出第2..n个牛其前面有多少比它编号小的个数,记为a[i],求该序列的 ...

  9. 洛谷P4248 [AHOI2013]差异(后缀自动机求lcp之和)

    题目见此 题解:首先所有后缀都在最后一个np节点,然后他们都是从1号点出发沿一些字符边到达这个点的,所以下文称1号点为根节点,我们思考一下什么时候会产生lcp,显然是当他们从根节点开始一直跳相同节点的 ...

随机推荐

  1. 小程序之rpx适配方案

    官网文档: 我的理解: rpx是自适应单位 计算方式: 1rpx = 设备屏幕宽度 / 750 注意:750是官网规定 为什么选择iPhone6为标准,作为开发模拟? 因为在iPhone6中,1px ...

  2. SaaS上云工具包为企业应用构筑上云之梯

    导语:本文中,阿里云资深技术专家郑刚将聚焦SaaS上云工具包如何帮助企业上云,包括产品上云.商品上市.服务上心,讲述了SaaS上云工具包为客户和伙伴提供的价值.在SaaS上云工具包整体解决方案的帮助下 ...

  3. Shiro学习(2)身份验证

    身份验证,即在应用中谁能证明他就是他本人.一般提供如他们的身份ID一些标识信息来表明他就是他本人,如提供身份证,用户名/密码来证明. 在shiro中,用户需要提供principals (身份)和cre ...

  4. luoguP3690 【模板】Link Cut Tree (动态树)[LCT]

    题目背景 动态树 题目描述 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...

  5. 删除maven项目后eclipse无法启动

    An internal error occurred during: "reload maven project". java.lang.NullPointerExceptio   ...

  6. 使用Jedis操作Redis-使用Java语言在客户端操作---set类型

    原文地址:http://www.cnblogs.com/lixianyuan-org/p/9509696.html 1 //测试set数据类型 2 /** 3 * 在Redis中,我们可以将Set类型 ...

  7. TLS/SSL 协议 - ClientHello

    ClientHello 在一次新的握手流程中,ClientHello消息总是第一条消息.这条消息将客户端的功能和首选项传送给服务器.客户端会在新建连接后,希望重新协商或者响应服务器发起的重新协商请求( ...

  8. jmeter 读写excel插件编写教程系列(1) -开篇

    不知道为什么,jmeter 竟然不提供 读写excel 的Sampler! 但是在我们自动化接口测试过程中,参数化.保存测试数据,用excel 是比较好的解决方案! 接下来一段儿时间,大虫会抽出一些时 ...

  9. js面向对象(一)---基本的概念、属性、方法

    一.什么是面向对象编程 1.用对象的思想去写代码,就是面向对象编程 2.我们一直在使用对象,如数组Array    时间Date //我们把系统自带的对象,叫做系统对象 var arr = new A ...

  10. css3 一个六边形 和 放大旋转动画DEMO演示

    <!DOCTYPE html> <html> <head> <meta charset="gb2312"> <title> ...