二分查找求出k大串, 然后正反做后缀数组, RMQ求LCP, 时间复杂度O(NlogN+logN)

---------------------------------------------------------------------

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
 
using namespace std;
 
typedef long long ll;
 
const int maxlog = 20;
const int maxn = 100009;
 
int N, Q;
 
inline int readint() {
char c = getchar();
for(; !isdigit(c); c = getchar());
int ret = 0;
for(; isdigit(c); c = getchar())
ret = ret * 10 + c - '0';
return ret;
}
 
inline ll readll() {
char c = getchar();
for(; !isdigit(c); c = getchar());
ll ret = 0;
for(; isdigit(c); c = getchar())
ret = ret * 10 + c - '0';
return ret;
}
 
struct SA {
int Sa[maxn], Rank[maxn], Height[maxn], cnt[maxn], RMQ[maxlog][maxn];
ll Sm[maxn];
char S[maxn];
#define Cmp(a, b) ((y[a] == y[b]) && (y[a + k] == y[b + k]))
#define b(i) (1 << (i))
void Build() {
int m = 'z' + 1, *x = Rank, *y = Height;
for(int i = 0; i < m; i++) cnt[i] = 0;
for(int i = 0; i < N; i++) cnt[x[i] = S[i]]++;
for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1];
for(int i = N; i--; ) Sa[--cnt[x[i]]] = i;
for(int k = 1, p = 0; k <= N; k <<= 1, p = 0) {
for(int i = N - k; i < N; i++) y[p++] = i;
for(int i = 0; i < N; i++)
if(Sa[i] >= k) y[p++] = Sa[i] - k;
for(int i = 0; i < m; i++) cnt[i] = 0;
for(int i = 0; i < N; i++) cnt[x[y[i]]]++;
for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1];
for(int i = N; i--; ) Sa[--cnt[x[y[i]]]] = y[i];
swap(x, y);
p = 1;
x[Sa[0]] = 0;
for(int i = 1; i < N; i++)
x[Sa[i]] = Cmp(Sa[i], Sa[i - 1]) ? p - 1 : p++;
if(p >= N) break;
m = p;
}
for(int i = 0; i < N; i++) Rank[Sa[i]] = i;
Height[0] = 0;
for(int i = 0, h = 0; i < N; i++) if(Rank[i]) {
if(h) h--;
while(S[i + h] == S[Sa[Rank[i] - 1] + h]) h++;
Height[Rank[i]] = h;
}
}
void Query_Init() {
Sm[0] = N - Sa[0] - 1;
for(int i = 1; i < N; i++) Sm[i] = Sm[i - 1] + N - Sa[i] - Height[i] - 1;
for(int i = 0; i < N; i++) RMQ[0][i] = Height[i];
for(int i = 1; b(i) <= N; i++)
for(int j = 0; j + b(i) <= N; j++)
RMQ[i][j] = min(RMQ[i - 1][j], RMQ[i - 1][j + b(i - 1)]);
}
int LCP(int x, int y) {
x = Rank[x], y = Rank[y];
if(x == y) return N;
if(x > y) swap(x, y);
x++;
int Log = 0;
while(b(Log) <= y - x + 1) Log++;
Log--;
return min(RMQ[Log][x], RMQ[Log][y - b(Log) + 1]);
}
pair<int, int> Get(ll v) {
int p = lower_bound(Sm, Sm + N, v) - Sm;
if(p >= N) return make_pair(-1, -1);
if(p) v -= Sm[p - 1];
return make_pair(Sa[p], Sa[p] + v + Height[p] - 1);
}
} A, B;
 
void Init() {
N = readint(), Q = readint();
char c = getchar();
for(; !islower(c); c = getchar());
A.S[0] = B.S[N - 1] = c;
for(int i = 1; i < N; i++)
A.S[i] = B.S[N - i - 1] = getchar();
A.S[N] = B.S[N] = '$';
N++;
}
 
#define L(x) x.first
#define R(x) x.second
 
void Work() {
A.Build(), A.Query_Init();
B.Build(), B.Query_Init();
ll l, r;
while(Q--) {
l = readll(), r = readll();
pair<int, int> L = A.Get(l), R = A.Get(r);
if(L(L) == -1 || L(R) == -1) {
puts("-1");
} else {
int mn = min(R(L) - L(L) + 1, R(R) - L(R) + 1);
int a = min(A.LCP(L(L), L(R)), mn);
int b = min(B.LCP(N - R(L) - 2, N - R(R) - 2), mn);
printf("%lld\n", ll(a) * a + ll(b) * b);
}
}
}
 
int main() {
Init();
Work();
return 0;
}

---------------------------------------------------------------------

3230: 相似子串

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 1186  Solved: 282
[Submit][Status][Discuss]

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'组成

Source

BZOJ 3230: 相似子串( RMQ + 后缀数组 + 二分 )的更多相关文章

  1. BZOJ 1717 [USACO06DEC] Milk Patterns (后缀数组+二分)

    题目大意:求可重叠的相同子串数量至少是K的子串最长长度 洛谷传送门 依然是后缀数组+二分,先用后缀数组处理出height 每次二分出一个长度x,然后去验证,在排序的后缀串集合里,有没有连续数量多于K个 ...

  2. 【题解】回文串 APIO 2014 BZOJ 3676 COGS 1985 Manacher+后缀数组+二分

    这题可以用回文自动机来做,但是我并没有学,于是用Manacher+SA的做法O(nlogn)水过 首先,看到回文串就能想到用Manacher 同样还是要利用Manacher能不重复不遗漏地枚举每个回文 ...

  3. POJ-1743 Musical Theme(最长不可重叠子串,后缀数组+二分)

    A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the ...

  4. cogs249 最长公共子串(后缀数组 二分答案

    http://cogs.pro:8080/cogs/problem/problem.php?pid=pxXNxQVqP 题意:给m个单词,让求最长公共子串的长度. 思路:先把所有单词合并成一个串(假设 ...

  5. POJ 3294 Life Forms [最长公共子串加强版 后缀数组 && 二分]

    题目:http://poj.org/problem?id=3294 Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total Submiss ...

  6. UVA-11107 Life Forms(求出现K次的子串,后缀数组+二分答案)

    题解: 题意: 输入n个DNA序列,你的任务是求出一个长度最大的字符串,使得它在超过一半的DNA序列中出现.如果有多解,按照字典序从小到大输入所有解. 把n个DNA序列拼在一起,中间用没有出现过的字符 ...

  7. BZOJ 3230 相似子串 | 后缀数组 二分 ST表

    BZOJ 3230 相似子串 题面 题解 首先我们要知道询问的两个子串的位置. 先正常跑一遍后缀数组并求出height数组. 对于每一个后缀suffix(i),考虑以i开头的子串有多少是之前没有出现过 ...

  8. BZOJ 4556 [Tjoi2016&Heoi2016]字符串 ——后缀数组 ST表 主席树 二分答案

    Solution 1: 后缀数组暴力大法好 #include <map> #include <cmath> #include <queue> #include &l ...

  9. BZOJ 3230: 相似子串

    3230: 相似子串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1485  Solved: 361[Submit][Status][Discuss ...

随机推荐

  1. jquery实现隐藏显示层动画效果、仿新浪字符动态输入、tab效果

    已经有两年多没登陆csdn账号了,中间做了些旁的事,可是现在却还是回归程序,但改做前端了,虽然很多东西都已忘得差不多了,但还是应该摆正心态,慢慢来,在前端漫游,做一只快乐双鱼. 路是一步一步走出来的, ...

  2. hdu 2768

    求最大留下的观众,观众之间存在不能同时满足的关系,就是矛盾关系, 矛盾关系建边,建边是双向的所以最大匹配要/2 还有一种建图的方法:把观众分成两个集合,一个是投留下猫的,一个是投留下狗的 每个集合间没 ...

  3. Setup Factory

    Setup Factory   生成安装程序

  4. JFreeChat

    JFreeChart教程(一) 分类: java Component2007-05-31 15:53 39849人阅读 评论(30) 收藏 举报 jfreechartimportdataset图形ap ...

  5. 相见恨晚——MarkDown

    什么是MarkDown MarkDown是一种轻量级的标记语言 MarkDown使你更加关注文章的内容 MarkDown使文章的排版变得简单直接 什么情景下使用MarkDown 在我们熟悉的githu ...

  6. EasyUI特殊情况下的BUG整理

    前面有两篇: Easyui - combo[tree,box]下拉图标有间隙bug解决方法 http://blog.csdn.net/isea533/article/details/12996561 ...

  7. artdialog关闭弹出窗口

    打开 function opentree(){  var dialog = art.dialog({    title: '选择提交部门',      content:jQuery("#my ...

  8. Others in life

    耗电量主要是与电机有关,800W电机在48V下的工作电流大约是800/48=16.7A,因此其工作时间主要取决于电池的容量,如果电池容量是20Ah,那么大概也就连续工作1个小时左右,也就是30-40k ...

  9. php面向对象编程学习之高级特性

    前几天写了一篇关于php面向对象基础知识的博客,这两天看了php面向对象的高级特性,写出来记录一下吧,方便以后拿出来复习. 面向对象除了最基本的定义类之外,最主要就是因为面向的一些高级特性,运用这些高 ...

  10. 给js文件传递参数

    一.利用全局变量 这是最简单的一种方式,比如Google Adsense: <script type="text/javascript"> google_ad_clie ...