SPOJ SUBLEX Lexicographical Substring Search - 后缀数组
考虑后缀Trie。依次考虑每个后缀新增的本质不同的子串个数,显然,它是$n - sa[i] - height[i]$。
求出$height$数组后,求一求本质不同的子串个数的前缀和,可以对每个询问二分。
这里可以直接离线,$O(n + m)$扫一扫就好了。
Code
/**
* SPOJ
* Problem#SUBLEX
* Accepted
* Time: 30ms
* Memory: 19456k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean; typedef class Pair3 {
public:
int x, y, id;
}Pair3; typedef class Query {
public:
int k, s, t, id; boolean operator < (Query b) const {
return k < b.k;
}
}Query; const int N = 1e5 + , M = ; int n, m;
char str[N], bs[N];
int rk[N << ], sa[N], hei[N], cnt[N];
Pair3 ps[N], buf[N];
Query qs[M]; inline void init() {
scanf("%s", str + );
n = strlen(str + );
scanf("%d", &m);
for (int i = ; i <= m; i++)
scanf("%d", &qs[i].k), qs[i].id = i;
} inline void radix_sort(Pair3* x, Pair3* y) {
int m = ((n > ) ? (n) : ());
memset(cnt, , sizeof(int) * (m + ));
for (int i = ; i <= n; i++) cnt[x[i].y]++;
for (int i = ; i <= m; i++) cnt[i] += cnt[i - ];
for (int i = ; i <= n; i++) y[cnt[x[i].y]--] = x[i];
memset(cnt, , sizeof(int) * (m + ));
for (int i = ; i <= n; i++) cnt[y[i].x]++;
for (int i = ; i <= m; i++) cnt[i] += cnt[i - ];
for (int i = n; i; i--) x[cnt[y[i].x]--] = y[i];
} inline void build_sa() {
for (int i = ; i <= n; i++)
rk[i] = str[i];
for (int k = , dif = ; k <= n; k <<= , dif = ) {
for (int i = ; i <= n; i++)
ps[i].x = rk[i], ps[i].y = rk[i + k], ps[i].id = i;
radix_sort(ps, buf);
rk[ps[].id] = ++dif;
for (int i = ; i <= n; i++)
rk[ps[i].id] = (dif += (ps[i].x != ps[i - ].x || ps[i].y != ps[i - ].y));
if (dif == n)
break;
}
for (int i = ; i <= n; i++)
sa[rk[i]] = i;
} inline void get_height() {
for (int i = , j, k = ; i <= n; i++) {
if (k) k--;
if (rk[i] > ) {
for (j = sa[rk[i] - ]; i + k <= n && j + k <= n && str[i + k] == str[j + k]; k++);
hei[rk[i]] = k;
} else
hei[] = ;
}
} inline void solve() {
build_sa();
get_height();
// for (int i = 1; i <= n; i++)
// cerr << hei[i] << " ";
// cerr << endl;
sort(qs + , qs + m + );
long long cur = ;
for (int i = , nq = , delta; i <= n && nq <= m; i++) {
delta = n - sa[i] + - hei[i];
if (cur + delta < qs[nq].k)
cur += delta;
else {
qs[nq].s = sa[i], qs[nq].t = sa[i] + hei[i] + (qs[nq].k - cur);
nq++, i--;
}
}
for (int i = ; i <= m; i++)
while (qs[i].id != i)
swap(qs[qs[i].id], qs[i]);
for (int i = ; i <= m; i++) {
int len = qs[i].t - qs[i].s;
memcpy(bs, str + qs[i].s , len);
bs[len] = ;
puts(bs);
}
} int main() {
init();
solve();
return ;
}
SPOJ SUBLEX Lexicographical Substring Search - 后缀数组的更多相关文章
- 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 (Lexicographical Substring Search) RE的欢迎来看看
SPOJ.com - Problem SUBLEX 这么裸的一个SAM,放在了死破OJ上面就是个坑. 注意用SAM做的时候输出要用一个数组存下来,然后再puts,不然一个一个字符输出会更慢. 还有一个 ...
- Spoj SUBLEX - Lexicographical Substring Search
Dicription Little Daniel loves to play with strings! He always finds different ways to have fun with ...
- SP7258 SUBLEX - Lexicographical Substring Search - 后缀自动机,dp
给定一个字符串,求本质不同排名第k小的子串 Solution 后缀自动机上每条路径对应一个本质不同的子串 按照 TRANS 图的拓扑序,DP 计算出每个点发出多少条路径 (注意区别 TRANS 图的拓 ...
- SPOJ 7258 Lexicographical Substring Search [后缀自动机 DP]
题意:给一个长度不超过90000的串S,每次询问它的所有不同子串中,字典序第K小的,询问不超过500个. 第一道自己做的1A的SAM啦啦啦 很简单,建SAM后跑kth就行了 也需要按val基数排序倒着 ...
- SPOJ7258 SUBLEX - Lexicographical Substring Search(后缀自动机)
Little Daniel loves to play with strings! He always finds different ways to have fun with strings! K ...
- spoj SUBLEX - Lexicographical Substring Search【SAM】
先求出SAM,然后考虑定义,点u是一个right集合,代表了长为dis[son]+1~dis[u]的串,然后根据有向边转移是添加一个字符,所以可以根据这个预处理出si[u],表示串u后加字符能有几个本 ...
- SP7258 SUBLEX - Lexicographical Substring Search(后缀自动机)
传送门 解题思路 首先建\(sam\),然后在拓扑序上\(dp\)一下,把每个点的路径数算出来,然后统计答案时就在自动机上\(dfs\)一下,仿照平衡树那样找第\(k\)小. 代码 #include& ...
随机推荐
- vim自动格式化
,gg 跳转到第一行 ,shift+v 转到可视模式 ,shift+g 全选 ,按下神奇的 = 你会惊奇的发现代码自动缩进了,呵呵,当然也可能是悲剧了.
- MYSQL导入数据时,出现错误:Incorrect string value: '\xF0\x9F...' for column 'XXX' at row 1
Incorrect string value: '\xF0\x9F...' for column 'XXX' at row 1 这个问题,原因是UTF-8编码有可能是两个.三个.四个字节.Emoji表 ...
- HAProxy实现mysql负载均衡
安装 yum install haproxy 修改配置 vi /etc/haproxy/haproxy.cfg 配置如下 global daemon nbproc 1 pidfile /var/r ...
- <7>Lua类的表的实例创建
根据上一节知识所述Lua中没有像C.C++.JAVA中的类概念,面向对象等 ,但我们可以模拟出来 如下 代码如下: --创建类的表 local Person = {} function Person: ...
- 17. Letter Combinations of a Phone Number(bfs)
Given a string containing digits from 2-9 inclusive, return all possible letter combinations that th ...
- sitecore系统教程之内容编辑器
内容编辑器 内容编辑器是一种编辑工具,可用于管理和编辑网站上的所有内容.它专为熟悉Sitecore及其包含的功能的经验丰富的内容作者而设计. 内容编辑器的外观和功能取决于用户的角色,本地安全设置以 ...
- 准备mysql-connector-java
下载mysql-connector-java:https://mvnrepository.com/artifact/mysql/mysql-connector-java 导入mysql-connect ...
- 20155228 2017-5-10 课堂测试:Arrays和String单元测试
20155228 2017-5-10 课堂测试:Arrays和String单元测试 题目和要求 在IDEA中以TDD的方式对String类和Arrays类进行学习 测试相关方法的正常,错误和边界情况 ...
- Python 字典(Dictionary) values()方法
描述 Python 字典(Dictionary) values() 函数以列表返回字典中的所有值. 语法 values()方法语法: dict.values() 参数 NA. 返回值 返回字典中的所有 ...
- 使用Flask-CKEditor集成富文本编辑框
使用Flask-CKEditor集成富文本编辑框 富文本编辑器即所见即所得编辑器,类似于文本编辑软件.它提供一系列按钮和下拉列表来为文本设置格式,编辑状态的文本样式即最终呈现出来的样式.在Web程序中 ...