Lexicographical Substring Search SPOJ - SUBLEX (后缀数组)
Lexicographical Substrings Search
\]
题意
给出一个字符串,求出这个字符串上字典序第 \(k\) 小的子串。
思路
对于给出的字符串,求出后缀数组,根据后缀数组的 \(height\) 数组,我们可以很容易得到一个字符的总子串个数是 \(\sum_{i=1}^{n} (n-sa[i]+1-height[i])\),利用这个式子,就可以求出第 \(k\) 小的子串了。
/***************************************************************
> File Name : a.cpp
> Author : Jiaaaaaaaqi
> Created Time : 2019年05月22日 星期三 18时17分02秒
***************************************************************/
#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lowbit(x) x & (-x)
#define mes(a, b) memset(a, b, sizeof a)
#define fi first
#define se second
#define pii pair<int, int>
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 1e5 + 10;
const int maxm = 1e5 + 10;
const ll mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std;
int n, m;
int cas, tol, T;
char s[maxn];
int a[maxn], sa[maxn], rk[maxn], tax[maxn], height[maxn], tp[maxn];
void rsort(int n, int m) {
for(int i=0; i<=m; i++) tax[i] = 0;
for(int i=1; i<=n; i++) tax[rk[tp[i]]]++;
for(int i=1; i<=m; i++) tax[i] += tax[i-1];
for(int i=n; i>=1; i--) sa[tax[rk[tp[i]]]--] = tp[i];
}
int cmp(int *f, int x, int y, int w) {
return f[x]==f[y] && f[x+w]==f[y+w];
}
void SA(int *a, int n, int m) {
for(int i=1; i<=n; i++) rk[i] = a[i], tp[i] = i;
rsort(n, m);
for(int w=1, p=1, i; p<n; w<<=1, m=p) {
for(p=0, i=n-w+1;i<=n; i++) tp[++p] = i;
for(i=1; i<=n; i++) if(sa[i]>w) tp[++p] = sa[i]-w;
rsort(n, m), swap(tp, rk);
rk[sa[1]] = p = 1;
for(i=2; i<=n; i++) rk[sa[i]] = cmp(tp, sa[i], sa[i-1], w) ? p : ++p;
}
int j, k=0;
for(int i=1; i<=n; height[rk[i++]] = k)
for(k=k ? k-1 : k, j=sa[rk[i]-1]; a[i+k]==a[j+k]; k++);
}
int main() {
scanf("%s", s+1);
n = strlen(s+1);
for(int i=1; i<=n; i++) {
a[i] = s[i];
}
SA(a, n, 260);
// for(int i=1; i<=n; i++) {
// printf("sa[%d] = %d height[%d] = %d\n", i, sa[i], i, height[i]);
// }
scanf("%d", &T);
while(T--) {
scanf("%d", &m);
for(int i=1; i<=n; i++) {
if(m > n-sa[i]+1-height[i]) {
m -= (n-sa[i]+1-height[i]);
} else {
int last = sa[i] + height[i] - 1;
last += m;
// printf("%d %d\n", sa[i], last);
for(int j=sa[i]; j<=last; j++) {
printf("%c", s[j]);
}
printf("\n");
break;
}
}
}
return 0;
}
Lexicographical Substring Search SPOJ - SUBLEX (后缀数组)的更多相关文章
- Lexicographical Substring Search SPOJ - SUBLEX (后缀自动机)
Lexicographical Substrings Search \[ Time Limit: 149 ms \quad Memory Limit: 1572864 kB \] 题意 给出一个字符串 ...
- 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 - Lexicographical Substring Search 后缀自动机 / 后缀数组
SUBLEX - Lexicographical Substring Search Little Daniel loves to play with strings! He always finds ...
- spoj 7258 Lexicographical Substring Search (后缀自动机)
spoj 7258 Lexicographical Substring Search (后缀自动机) 题意:给出一个字符串,长度为90000.询问q次,每次回答一个k,求字典序第k小的子串. 解题思路 ...
- SPOJ SUBLEX 7258. Lexicographical Substring Search
看起来像是普通的SAM+dfs...但SPOJ太慢了......倒腾了一个晚上不是WA 就是RE ..... 最后换SA写了...... Lexicographical Substring Searc ...
- [SPOJ7258]Lexicographical Substring Search
[SPOJ7258]Lexicographical Substring Search 试题描述 Little Daniel loves to play with strings! He always ...
- 【SPOJ】7258. Lexicographical Substring Search(后缀自动机)
http://www.spoj.com/problems/SUBLEX/ 后缀自动机系列完成QAQ...撒花..明天or今晚写个小结? 首先得知道:后缀自动机中,root出发到任意一个状态的路径对应一 ...
- SPOJ PHRASES 后缀数组
题目链接:http://www.spoj.com/problems/PHRASES/en/ 题意:给定n个字符串,求一个最长的子串至少在每个串中的不重叠出现次数都不小于2.输出满足条件的最长子串长度 ...
- SPOJ REPEATS 后缀数组
题目链接:http://www.spoj.com/problems/REPEATS/en/ 题意:首先定义了一个字符串的重复度.即一个字符串由一个子串重复k次构成.那么最大的k即是该字符串的重复度.现 ...
随机推荐
- C++指针与数组、函数、动态内存分配
C++指针 指针是用来存储地址的变量. 对于二维数组来说: a:代表的是首行地址: *a:代表的是首元素地址: **a:首元素: a+1:第二行地址: *a+2:首先*a是首元素地址,在首元素地址上+ ...
- MarkDown的常规用法
MarkDown的常规用法 标题 # 一级标题 ## 二级标题 ... ###### 六级标题 列表 第二级 - 和 空格 + 和 空额 * 和 空格 第三级 代码块 多行代码块 3个` 回车 单行代 ...
- ubuntu开机自动挂载硬盘
1. 查看硬盘信息 df -h 命令找到目标硬盘(可根据 磁盘分区(路径).分区大小.挂载点 确认/定位 目标) sudo blkid 命令找到目标硬盘的UUID,(关注一下分区的格式化类型,如ex ...
- Introducing KSQL: Streaming SQL for Apache Kafka
Update: KSQL is now available as a component of the Confluent Platform. I’m really excited to announ ...
- 记录一次使用NPOI遇到的问题
在.net 下一般使用NPOI操作Excel相信大家都不陌生,但是本人在操作过程中遇到一个比较奇怪的问题,特写此博客记录与大家分享. 例子是使用Winform,点击按钮时弹出打开文件对话框,然后选择文 ...
- C# yield checked,unchecked lock语句(C#学习笔记04)
特殊语句 yield语句 yield用于终止迭代 只能使用在返回类型必须为 IEnumerable.IEnumerable<T>.IEnumerator 或 IEnumerator< ...
- intent 和 Broadcast Receiver之间的通信
工作原理是通过封装一个service启动的一个线程产生的随机数封装到intent对象传递给Activity,Activity接受到后讲结果输出到屏幕. java的代码: package jm.out; ...
- java。JDK的API,版本1.6.0中文版下载
转载自https://blog.csdn.net/xiao9469/article/details/87783561 链接: https://pan.baidu.com/s/1YqrbTD_msTmn ...
- 2019 找钢网java面试笔试题 (含面试题解析)
本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.找钢网等公司offer,岗位是Java后端开发,因为发展原因最终选择去了找钢网,入职一年时间了,也成为了面试官 ...
- Promise介绍及使用场景
Promise 介绍 Promise 是一个构造函数,是异步编程的一种解决方案.所谓Promse,它本身就是一个容器,里面保存着异步操作的结果,对的,这和回调函数类似. Promise 容器本身不是异 ...