二分查找求出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. 开发该选择Blocks还是Delegates(转)

    原文链接:http://blog.stablekernel.com/blocks-or-delegates/ By Joe Conway,CEO | Jul 11,2013 11:29:00 AM 有 ...

  2. 把war包放到Tomcat安装文件夹下,不能直接訪问的解决方式

    临床表现: Tomcat启动后首页能訪问(http://localhost:8080/). 将自己写的一个webprojectwar包放到Tomcat安装文件夹下的/webapps以下(比方hello ...

  3. 树形dp-hdu-4714-Tree2cycle

    题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4714 题目意思: 给一棵树,去掉一条边和增加一条边的花费都为1,求最小的花费,使该树变成一个环. 解 ...

  4. IIS的安装

    xp上好像只能装IIS5,IIS6根本就装不了

  5. bootstarp基本模板

    <!DOCTYPE html><!--html5文档格式--> <html lang="zh-CN"><!--申明语言是中文简体--> ...

  6. MySQL报错:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password:NO)

    1.关闭mysql   # service mysqld stop2.屏蔽权限   # mysqld_safe --skip-grant-table   屏幕出现: Starting demo fro ...

  7. 解压tomcat后一闪而过的问题

    解压tomcat压缩包后,直接点击startup会出现一闪而过. 免安装的tomcat双击startup.bat后,启动窗口一闪而过,而且tomcat服务未启动. 原因是:在启动tomcat是,需要读 ...

  8. JVM学习之JVM1.6 GC详解

    转自:http://www.cnblogs.com/ggjucheng/p/3977384.html,多谢分享 前言  JVM GC是JVM的内存回收算法,调整JVM GC(Garbage Colle ...

  9. python打包成.exe工具py2exe0-----No such file or directory错误

    转自:http://justcoding.iteye.com/blog/900993 一.简介 py2exe是一个将python脚本转换成windows上的可独立执行的可执行程序(*.exe)的工具, ...

  10. mysql获取各种日期

    select curdate(); --获取当前日期 select last_day(curdate()); --获取当月最后一天. select DATE_ADD(curdate(),interva ...