BZOJ3230: 相似子串【后缀数组】
Description
Input
输入第1行,包含3个整数N,Q。Q代表询问组数。
第2行是字符串S。
接下来Q行,每行两个整数i和j。(1≤i≤j)。
Output
输出共Q行,每行一个数表示每组询问的答案。如果不存在第i个子串或第j个子串,则输出-1。
Sample Input
5 3
ababa
3 5
5 9
8 10
Sample Output
18
16
-1
HINT
样例解释
第1组询问:两个子串是“aba”,“ababa”。f = 32 + 32 = 18。
第2组询问:两个子串是“ababa”,“baba”。f = 02 + 42 = 16。
第3组询问:不存在第10个子串。输出-1。
数据范围
N≤100000,Q≤100000,字符串只由小写字母'a'~'z'组成
直接正串反串建立SA然后求出lcp就可以了。。。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pi;
typedef long long ll;
const int N = 1e5 + 10;
const int LOG = 20;
struct Suffix_Array {
int s[N], n, m;
int c[N], x[N], y[N];
int height[N], sa[N], rank[N];
int st[N][LOG], Log[N];
ll sum[N];
void init(int len, char *c) {
n = len, m = 0;
for (int i = 1; i <= len; i++) {
s[i] = c[i];
m = max(m, s[i]);
}
}
void radix_sort() {
for (int i = 1; i <= m; i++) c[i] = 0;
for (int i = 1; i <= n; i++) c[x[y[i]]]++;
for (int i = 1; i <= m; i++) c[i] += c[i - 1];
for (int i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i];
}
void buildsa() {
for (int i = 1; i <= n; i++) x[i] = s[i], y[i] = i;
radix_sort();
int now;
for (int k = 1; k <= n; k <<= 1) {
now = 0;
for (int i = n - k + 1; i <= n; i++) y[++now] = i;
for (int i = 1; i <= n; i++) if (sa[i] > k) y[++now] = sa[i] - k;
radix_sort();
y[sa[1]] = now = 1;
for (int i = 2; i <= n; i++) y[sa[i]] = (x[sa[i]] == x[sa[i - 1]] && x[sa[i] + k] == x[sa[i - 1] + k]) ? now : ++now;
swap(x, y);
if (now == n) break;
m = now;
}
}
void buildrank() {
for (int i = 1; i <= n; i++) rank[sa[i]] = i;
}
void buildsum() {
for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + n - sa[i] + 1 - height[i];
}
void buildheight() {
for (int i = 1; i <= n; i++) if (rank[i] != 1) {
int k = max(height[rank[i - 1]] - 1, 0);
for (; s[i + k] == s[sa[rank[i] - 1] + k]; k++);
height[rank[i]] = k;
}
}
void buildst() {
Log[1] = 0;
for (int i = 2; i < N; i++) Log[i] = Log[i >> 1] + 1;
for (int i = 1; i <= n; i++) st[i][0] = height[i];
for (int j = 1; j < LOG; j++) {
for (int i = 1; i + (1 << (j - 1)) <= n; i++) {
st[i][j] = min(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
}
}
}
int queryst(int l, int r) {
if (l == r) return n - sa[l] + 1;
if (l > r) swap(l, r);
++l;
int k = Log[r - l + 1];
return min(st[l][k], st[r - (1 << k) + 1][k]);
}
int querylcp(int la, int ra, int lb, int rb) {
return min(min(ra - la + 1, rb - lb + 1), queryst(rank[la], rank[lb]));
}
bool cmpsubstring(int la, int ra, int lb, int rb) {
int lcp = querylcp(la, ra, lb, rb);
if (ra - la + 1 == lcp) return 1;
if (rb - lb + 1 == lcp) return 0;
return s[la + lcp] < s[lb + lcp];
}
pi findkth(ll k) {
int pos = lower_bound(sum + 1, sum + n + 1, k) - sum;
return pi(sa[pos], sa[pos] + height[pos] + k - sum[pos - 1] - 1);
}
ll getrank(int l, int r) {
int pos = rank[l], len = r - l + 1;
for (int i = LOG - 1; i >= 0; i--) {
if (pos > (1 << i) && st[pos - (1 << i) + 1][i] >= len) {
pos -= (1 << i);
}
}
return sum[pos - 1] + len - height[pos];
}
void build(int len, char *c) {
init(len, c);
buildsa();
buildrank();
buildheight();
buildsum();
buildst();
}
} Sa, revSa;
char s[N], revs[N];
int len, q;
int main() {
scanf("%d %d", &len, &q);
scanf("%s", s + 1);
for (int i = 1; i <= len; i++) revs[i] = s[len - i + 1];
Sa.build(len, s);
revSa.build(len, revs);
while (q--) {
ll x, y; scanf("%lld %lld", &x, &y);
if (Sa.sum[len] < max(x, y)) {
printf("-1\n");
continue;
}
pi curx = Sa.findkth(x), cury = Sa.findkth(y);
int a = Sa.querylcp(curx.first, curx.second, cury.first, cury.second);
int b = revSa.querylcp(len - curx.second + 1, len - curx.first + 1, len - cury.second + 1, len - cury.first + 1);
printf("%lld\n", 1ll * a * a + 1ll * b * b);
}
return 0;
}
BZOJ3230: 相似子串【后缀数组】的更多相关文章
- BZOJ3230 相似子串[后缀数组+二分+st表]
BZOJ3230 相似子串 给一个串,查询排名i和j的子串longest common suffix和longest common prefix 思路其实还是蛮好想的,就是码起来有点恶心.可以发现后缀 ...
- [BZOJ3230]相似子串(后缀数组)
显然可以通过后缀数组快速找到询问的两个串分别是什么,然后正反各建一个后缀数组来求两个串的LCP和LCS即可. #include<cstdio> #include<cstring> ...
- poj 2774 最长公共子串 后缀数组
Long Long Message Time Limit: 4000MS Memory Limit: 131072K Total Submissions: 25752 Accepted: 10 ...
- URAL 1297 最长回文子串(后缀数组)
1297. Palindrome Time limit: 1.0 secondMemory limit: 64 MB The “U.S. Robots” HQ has just received a ...
- poj 1743 Musical Theme(最长重复子串 后缀数组)
poj 1743 Musical Theme(最长重复子串 后缀数组) 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复 ...
- Cogs 1709. [SPOJ705]不同的子串 后缀数组
题目:http://cojs.tk/cogs/problem/problem.php?pid=1709 1709. [SPOJ705]不同的子串 ★★ 输入文件:subst1.in 输出文件: ...
- BZOJ 1396: 识别子串( 后缀数组 + 线段树 )
这道题各位大神好像都是用后缀自动机做的?.....蒟蒻就秀秀智商写一写后缀数组解法..... 求出Height数组后, 我们枚举每一位当做子串的开头. 如上图(x, y是height值), Heigh ...
- BZOJ 3230 相似子串 | 后缀数组 二分 ST表
BZOJ 3230 相似子串 题面 题解 首先我们要知道询问的两个子串的位置. 先正常跑一遍后缀数组并求出height数组. 对于每一个后缀suffix(i),考虑以i开头的子串有多少是之前没有出现过 ...
- bzoj 3230 相似子串——后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3230 作出后缀数组,从 LCP 看每个位置对于本质不同子串的贡献,而且他们已经按前面部分排好 ...
- 【poj1743-Musical Theme】不可重叠最长重复子串-后缀数组
http://poj.org/problem?id=1743 这题是一道后缀数组的经典例题:求不可重叠最长重复子串. 题意: 有N(1 <= N <=20000)个音符的序列来表示一首乐曲 ...
随机推荐
- iOS Socket编程-C语言版(TCP)
. TCP Socket编程 TCP是面向连接的,安全可靠的传输层协议.TCP的程序基本框架设计图: TCP的程序基本框架设计图.jpg 注意:Socket通信一定有要服务端和客户端. 1.1 TCP ...
- RabbitMQ入门_06_深入了解ack
A. Delivery Tag 参考资料:https://www.rabbitmq.com/confirms.html 仔细查看一下 Consumer 的回调方法: public void handl ...
- 算法笔记--java的BigInteger类及BigDecimal类
引包:import java.math.*; BigInteger类: 可以使用构造方法:public BigInteger(String val),或者valueOf(int)函数,如: BigIn ...
- [转]mysql-mmm集群(多实例)
一.需求说明 最近一直在学习mysql-mmm,想以后这个架构也能用在我们公司的业务上,我们公司的业务是单机多实例部署,所以也想把mysql-mmm部署成这样,功夫不负有心人,我成功了,和大家分享一下 ...
- 20170711xlVBA批量制图一例
Public Sub GatherDataPicker() Application.ScreenUpdating = False Application.DisplayAlerts = False A ...
- axios构建缓存池存储基础数据
项目中经常出现需要多次使用的后端数据,通常的做法是通过变量缓存数据,或者通过类似vuex的东西来进行缓存,但是麻烦在于很可能需要判断一大堆的条件,或者说如果有权限控制的时候数据能否读取也是很麻烦的事情 ...
- Professional layer CodeForces - 1103D (状压,gcd)
大意: 给定$n$元素序列$a$, 现在想要让$gcd(a_1,a_2,...,a_n)=1$. 对于每个$a_i$可以除以一个不超过$k$的因子, 代价为$e_i$, 假设一共选择了$x$个元素去除 ...
- hdu1238 kmp
You are given a number of case-sensitive strings of alphabetic characters, find the largest string X ...
- 微信小程序自定义模态框(字体图标)
组件已经传到github,自行下载:https://github.com/JinZhenZon/miniapp-customModel 支持如下配置: { outWidth <number&g ...
- hdu2159完全背包
md心里有事的时候不能写题操 FATE Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...