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& ...
随机推荐
- Jenkins自动化构建(二)众多问题
1.反向代理设置有误 系统管理页面提示,反向代理设置有误,其实这是由于URL设置有问题: 打开系统管理-->系统设置-->URL Jenkins URL设置有问题,改一下,去掉jenkin ...
- linux du查看文件所占大小
Linux du命令也是查看使用空间的,但是与df命令不同的是Linux du命令是对文件和目录磁盘使用的空间的查看,还是和df命令有一些区别的. 1.命令格式: du [选项][文件] 2.命令功能 ...
- Sublime text3 经常出现 “ There are no packages avaliable for installation” 解决方法
对应这个问题,一开始在度娘上找到很多答案,包括将json文件放在本地然后通过 package setting 更改的,发现其实不好使,原因未知. 后来测试了在hosts文件添加sublime text ...
- Mysql由浅入深
1. Mysql的安装方式 1. yum安装mysql 适合对数据库要求不太高的场合,例如:并发不大,公司内部,企业内部. 1. 官网下载yum源,wget https://dev.mysql.c ...
- STL算法中函数对象和谓词
函数对象和谓词定义 函数对象: 重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象.一个类对象,表现出一个函数的特征,就是通过“对象名+(参数列 ...
- Nginx技术研究系列1-通过应用场景看Nginx的反向代理
随着我们业务规模的不断增长,整个系统规模由两年前的几十台服务器,井喷到现在2个数据中心,接近400台服务器,上百个WebApi站点,上百个域名. 这么多的WebApi站点这么多的域名,管理和维护成本很 ...
- Nginx配置基础-location
location表达式类型 ~ 表示执行一个正则匹配,区分大小写~* 表示执行一个正则匹配,不区分大小写^~ 表示普通字符匹配.使用前缀匹配.如果匹配成功,则不再匹配其他location.= 进行普通 ...
- MySQL超时配置
connect_timeout:连接响应超时时间.服务器端在这个时间内如未连接成功,则会返回连接失败. wait_timeout:连接空闲超时时间.与服务器端无交互状态的连接,直到被服务器端强制关闭而 ...
- 20165305 苏振龙《Java程序设计》第一周学习总结
20165305 <Java程序设计>第一周学习总结 教材学习内容总结 我重点学习了jdk安装后面的第一章内容,算是更进一步的的了解了一些Java方面的基础知识. Java平台概论 Jav ...
- 【转】Kylin介绍 (很有用)
转:http://blog.csdn.net/yu616568/article/details/48103415 Kylin是ebay开发的一套OLAP系统,与Mondrian不同的是,它是一个MOL ...