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& ...
随机推荐
- vue+element-ui中的表单验证(电话等等)
1. 2. 3. ============================================================上代码============================ ...
- Windows Server 2008 安装 10.2.0.5 单实例
需求:Windows Server 2008 安装 10.2.0.5 单实例 原以为非常简单的一次任务,实际却遇到了问题,故记录一下. 1.安装10.2.0.1 2.安装10.2.0.4 3.安装10 ...
- 18.搭建 vue 环境
第一步 node环境安装 1.1 如果本机没有安装node运行环境,请下载node 安装包进行安装1.2 如果本机已经安装node的运行换,请更新至最新的node 版本下载地址:https://nod ...
- TP5数据库操作方法
一.TP5数据库操作方法 1.name()方法作用 : 指定默认的数据表名(不含前缀)示例 : Db::name(‘weiba_post’);返回 : Db对象 2.setTable()方法作用 : ...
- Javascript-全局函数和局部函数作用域的理解
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- python基础-abstractmethod、__属性、property、setter、deleter、classmethod、staticmethod
python基础-abstractmethod.__属性.property.setter.deleter.classmethod.staticmethod
- 【impala学习之一】impala
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 CM5.4 一.ImpalaImpala是基于Hive的大数 ...
- sqlyog下载
sqlyog下载(附注册码):http://www.onlinedown.net/soft/24926.htm
- 接口作为方法的参数或返回值——List接口
接口作为方法的参数或返回值,源码可知,List为一个接口,ArraryList是的它的实现类: 其中,addNames方法中,入参和返回值都List接口,入参是多态的,编译看左,运行看右(访问成员方法 ...
- python遍历目录os.walk(''d:\\test2",topdown=False)
os.walk(top, topdown=True, onerror=None, followlinks=False)遍历目录,topdown=false表示先返回目录,后返回文件 参数说明: top ...