二分查找求出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. How Many Maos Does the Guanxi Worth

    How Many Maos Does the Guanxi Worth Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/5 ...

  2. Mock, 让你的开发脱离接口

    在前后台共同进行一个项目的时候常会遇到一种情景, 后台定义好接口,前端按照接口进行开发, 当前端开发完成后台接口却还没有开发完成, 这个时候要进行接口测试, 只能等后台开发完成才能测试, 在这中间浪费 ...

  3. 切换tab,并且动态添加标签

    <script type="text/javascript"> /*处理ie7.ie8不兼容getElementsByClassName*/ if(!document. ...

  4. ajax相关

    Javascript·部分: <script language="javascript" type="text/javascript" src=" ...

  5. 安装SQL Server 2012过程中出现“启用windows功能NetFx3时出错”(错误原因、详细分析及解决方法)以及在Windows Server2012上安装.NET Framework 3.5的详细分析及安装过程

           问题:在服务器(操作系统为Windows server 2012)上安装SQL Server 2012的过程中,安装停留在下图所示的界面上,显示”正在启用操作系统功能NetFx3”随后出 ...

  6. boost signal2 trackable

    挺简单的一个类,只是维护了一个成员 shared_ptr<detail::trackable_pointee> _tracked_ptr; 这样看来的话,所谓的track还是基于智能指针, ...

  7. leetcode Binary Tree Postorder Traversal python

    # Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x): # self.val = ...

  8. mysql获取各种日期

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

  9. Android minHeight/Width,maxHeight/Width

    在layout文件中,设置IamgeView的最大(最小)高度(宽度)时,需要同时设置android:adjustViewBounds="true",这样设置才会生效.在代码中设置 ...

  10. 利用JSP编程技术实现一个简单的购物车程序

    实验二   JSP编程 一.实验目的1. 掌握JSP指令的使用方法:2. 掌握JSP动作的使用方法:3. 掌握JSP内置对象的使用方法:4. 掌握JavaBean的编程技术及使用方法:5. 掌握JSP ...