[传送门]

先求出SA和height。然后找到 rank[l] 的 height 值。能成为相同子串的就是和rank[l]的lcp不小于 $len$ 的。二分出左右端点之后,主席树求第k小即可。

#include <bits/stdc++.h>

const int N = 1e5 + ;
char s[N];
int n, q; namespace SA {
int sa[N], rk[N], fir[N], sec[N], c[N], height[N];
int mn[N][], lg[N];
void build(int len, int num = ) {
register int i, j, k;
for (i = ; i <= num; i++) c[i] = ;
for (i = ; i <= len; i++) ++c[fir[i] = s[i]];
for (i = ; i <= num; i++) c[i] += c[i - ];
for (i = len; i >= ; i--) sa[c[fir[i]]--] = i;
for (k = ; k <= len; k <<= ) {
int cnt = ;
for (i = len - k + ; i <= len; i++) sec[++cnt] = i;
for (i = ; i <= len; i++) if (sa[i] > k) sec[++cnt] = sa[i] - k;
for (i = ; i <= num; i++) c[i] = ;
for (i = ; i <= len; i++) ++c[fir[i]];
for (i = ; i <= num; i++) c[i] += c[i - ];
for (i = len; i >= ; i--) sa[c[fir[sec[i]]]--] = sec[i], sec[i] = ;
std::swap(fir, sec);
fir[sa[]] = ; cnt = ;
for (i = ; i <= len; i++)
fir[sa[i]] = (sec[sa[i]] == sec[sa[i - ]] && sec[sa[i] + k] == sec[sa[i - ] + k]) ? cnt : ++cnt;
if (cnt == len) break;
num = cnt;
}
k = ;
for (i = ; i <= len; i++) rk[sa[i]] = i;
for (i = ; i <= len; i++) {
if (rk[i] == ) continue;
if (k) k--;
j = sa[rk[i] - ];
while (j + k <= len && i + k <= len && s[i + k] == s[j + k]) k++;
height[rk[i]] = k;
}
} inline int MIN(int a, int b) {
return height[a] < height[b] ? a : b;
} void init_RMQ(int n) {
for (int i = , j = ; i <= n; i++)
lg[i] = ( << (j + )) == i ? ++j : j;
for (int i = ; i <= n; i++)
mn[i][] = i;
for (int j = ; j < ; j++)
for (int i = ; i + ( << j) - <= n; i++)
mn[i][j] = MIN(mn[i][j - ], mn[i + ( << (j - ))][j - ]);
} int RMQ(int a, int b) {
int log = lg[b - a + ];
b -= ( << log) - ;
return MIN(mn[a][log], mn[b][log]);
} int LCP(int i, int j) {
i = rk[i], j = rk[j];
if (i > j) std::swap(i, j);
return height[RMQ(i + , j)];
}
} int root[N]; struct Seg {
struct Tree {
int lp, rp, sum;
} tree[N * ];
int tol;
inline void clear() {
tol = ;
memset(tree, , sizeof(tree));
}
void update(int &p, int q, int l, int r, int pos) {
tree[p = ++tol] = tree[q];
tree[p].sum++;
if (l == r) return;
int mid = l + r >> ;
if (pos <= mid) update(tree[p].lp, tree[q].lp, l, mid, pos);
else update(tree[p].rp, tree[q].rp, mid + , r, pos);
}
int query(int p, int q, int l, int r, int k) {
if (l == r) return l;
int mid = l + r >> ;
int sum = tree[tree[p].lp].sum - tree[tree[q].lp].sum;
if (sum >= k) return query(tree[p].lp, tree[q].lp, l, mid, k);
return query(tree[p].rp, tree[q].rp, mid + , r, k - sum);
}
} seg; int solve(int x, int y, int k) {
int len = y - x + ;
int L = SA::rk[x];
if (SA::height[L] >= len) {
int l = , r = L;
while (l <= r) {
int mid = l + r >> ;
if (SA::LCP(SA::sa[mid], x) >= len) L = mid, r = mid - ;
else l = mid + ;
}
}
int R = SA::rk[x];
if (SA::height[SA::rk[x] + ] >= len) {
int l = SA::rk[x] + , r = n;
while (l <= r) {
int mid = l + r >> ;
if (SA::LCP(x, SA::sa[mid]) >= len) R = mid, l = mid + ;
else r = mid - ;
}
}
//printf("%d %d\n", L, R);
if (k > seg.tree[root[R]].sum - seg.tree[root[L - ]].sum) return -;
return seg.query(root[R], root[L - ], , n, k);
} int main() {
freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &q);
scanf("%s", s + );
SA::build(n);
SA::init_RMQ(n);
seg.clear();
for (int i = ; i <= n; i++)
seg.update(root[i], root[i - ], , n, SA::sa[i]);
while (q--) {
int l, r, k;
scanf("%d%d%d", &l, &r, &k);
printf("%d\n", solve(l, r, k));
}
}
return ;
}

HDU6704 K-th occurrence的更多相关文章

  1. django模型操作

    Django-Model操作数据库(增删改查.连表结构) 一.数据库操作 1.创建model表        

  2. HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并)

    layout: post title: HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并) author: "luowentaoaa&quo ...

  3. HDU-6704 K-th occurrence

    Description You are given a string S consisting of only lowercase english letters and some queries. ...

  4. [2019CCPC网络赛][hdu6704]K-th occurrence(后缀数组&&主席树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6704 题意为查询子串s[l...r]第k次出现的位置. 写完博客后5分钟的更新 写完博客才发现这份代码 ...

  5. hdu6704 2019CCPC网络选拔赛1003 K-th occurrence 后缀自动机+线段树合并

    解题思路: fail树上用权值线段树合并求right/endpos集合,再用倍增找到待查询串对应节点,然后权值线段树求第k大. #include<bits/stdc++.h> using ...

  6. hdu6704 2019CCPC网络选拔赛1003 K-th occurrence 后缀数组

    题意:给你一个长度为n的字符串,有q个询问,每次询问一个子串s(l,r)第k次出现的位置,若子串出现次数少于k次输出-1. 解题思路:先把SA跑出来,然后对于每次询问可以由l和rank[]找到l在所有 ...

  7. HDU-6704 K-th occurrence(后缀数组+主席树)

    题意 给一个长度为n的字符串,Q次询问,每次询问\((l,r,k)\) , 回答子串\(s_ls_{l+1}\cdots s_r\) 第\(k\) 次出现的位置,若不存在输出-1.\(n\le 1e5 ...

  8. [转]vi command summary

    The following tables contain all the basic vi commands. *Starting vi* Command Description vi file st ...

  9. LeetCode 560. Subarray Sum Equals K (子数组之和等于K)

    Given an array of integers and an integer k, you need to find the total number of continuous subarra ...

随机推荐

  1. [转帖]IPC网络高清摄像机基础知识1(IPC芯片市场分析以及“搅局者”华为海思 “来自2013年”)

    IPC网络高清摄像机基础知识1(IPC芯片市场分析以及“搅局者”华为海思 “来自2013年”) 2016-06-02 14:23:49 Times_poem 阅读数 9734更多 分类专栏: IPC网 ...

  2. 解决source insight 4.0 不识别.cc文件的问题

    Options -> File Type Options, File Filter 中加入,*.cc 参考了C++ Primer Plus第五版中文版 P8 C++实现 源代码的扩展名 UNIX ...

  3. 在Windows 10中禁用自动文件夹类型发现

    点击下载注册表文件:https://files.cnblogs.com/files/Music/win10_automatic_folder_type_discovery.zip 已知Windows ...

  4. ubuntu docker inflxudb(安装 使用 备份 还原 以及python编码) telegraf Grafana

    inflxudb1.7.7 1.拉取最新的镜像 docker pull influxdb 2.运行实例: docker run -d --restart=always -p 8086:8086 -p ...

  5. 『序列 莫队 dp预处理』

    序列 Description 给定长度为n的序列:a1,a2,-,an,记为a[1:n]. 类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,-,ar-1,ar.若1≤l≤s≤t≤r≤n ...

  6. 《即时消息技术剖析与实战》学习笔记3——IM系统如何保证消息的实时性

    IM 技术经历过几次迭代升级,如图所示: 从简单.低效的短轮询逐步升级到相对效率可控的长轮询: 全双工的 Websocket 彻底解决了服务端的推送问题: 基于 TCP 长连接衍生的 IM 协议,能够 ...

  7. syntax error near unexpected token 脚本报错误解决

    hadoop老师给了一个shell文件,在windows里面瞅了一眼然后在ubuntu环境下运行就报错了.看了一些博客,用vim -b filename查看的时候发现每一行的末尾都多了一个^M.... ...

  8. java版的状态机实现

    状态机适用场景: C的操作,需要等到A.B的两个操作(A.B顺序操作),那就需要在 A.B之间创建一个状态机(state machine),C的操作需要状态机达到某一个状态才能进行 1. Overvi ...

  9. Sqoop import导入表时报错java.lang.ClassNotFoundException: org.json.JSONObject

    报错原因:sqoop缺少java-json.jar包. 解决方案:一. 下载java-json.jar包地址:https://download.csdn.net/download/qq_2213643 ...

  10. AD常用术语

    SMD : Surface Mounted Devices 表面贴装器件 PAD 焊盘