/*
一个性质? right集合中只有相邻的位置才会有用
那么考虑set启发式合并, 能够求出大概nlogn个有用的对
那么将这些对按照右端点排序, 查询也按照右端点排序就可以离线维护信息
然后需要维护答案的话?? 区间和一次函数取max???
应该有别的办法吧
普通线段树就好了
*/ #include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>
#include<queue>
#include<iostream>
#define ll long long
#define mmp make_pair
#define M 200010
using namespace std;
int read() {
int nm = 0, f = 1;
char c = getchar();
for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
return nm * f;
}
set<int> st[M];
set<int>::iterator it, tt;
int ch[M][26], fa[M], len[M], sz[M], ans[M], lst = 1, cnt = 1, n, m, tp;
char s[M];
vector<int> to[M];
struct Note {
int l, r, max;
bool operator < (const Note &b) const {
return this->r < b.r;
}
} note[M * 60], que[M]; void insert(int pl, int c) {
int p = ++cnt, f = lst;
lst = p;
len[p] = len[f] + 1;
while(f && !ch[f][c]) ch[f][c] = p, f = fa[f];
if(f == 0) fa[p] = 1;
else {
int q = ch[f][c];
if(len[q] == len[f] + 1) fa[p] = q;
else {
int nq = ++cnt;
len[nq] = len[f] + 1;
fa[nq] = fa[q];
memcpy(ch[nq], ch[q], sizeof(ch[q]));
fa[p] = fa[q] = nq;
while(f && ch[f][c] == q) ch[f][c] = nq, f = fa[f];
}
}
sz[p] = 1;
st[p].insert(pl);
}
int id[M]; bool cmp(int a, int b) {
return sz[a] > sz[b];
} void dfs(int now) {
id[now] = now;
int flag = sz[now];
for(int i = 0; i < to[now].size(); i++) {
int vj = to[now][i];
dfs(vj);
sz[now] += sz[vj];
}
if(now == 1) return;
sort(to[now].begin(), to[now].end(), cmp);
if(to[now].size() != 0) {
id[now] = id[to[now][0]];
if(flag) {
int v = *st[now].begin();
it = st[id[now]].lower_bound(v);
if(it != st[id[now]].end()) {
note[++tp] = (Note) {
v, *it, len[now]
};
}
if(it != st[id[now]].begin()) {
it--;
note[++tp] = (Note) {
*it, v, len[now]
};
}
st[id[now]].insert(v);
}
for(int i = 1; i < to[now].size(); i++) {
int vj = to[now][i];
it = st[id[vj]].begin();
while(it != st[id[vj]].end()) {
int v = *it++;
tt = st[id[now]].lower_bound(v);
if(tt != st[id[now]].end()) {
note[++tp] = (Note) {
v, *tt, len[now]
};
}
if(tt != st[id[now]].begin()) {
tt--;
note[++tp] = (Note) {
*tt, v, len[now]
};
}
st[id[now]].insert(v);
}
}
}
} struct Black_ {
#define ls now << 1
#define rs now << 1 | 1
#define lson l, mid, now << 1
#define rson mid + 1, r, now << 1 | 1
int t[M << 2], len[M << 2], ver[M << 2], maxx[M << 2]; void build(int l, int r, int now) {
len[now] = r - l + 1;
ver[now] = -0x3e3e3e3e;
if(l == r) return;
int mid = (l + r) >> 1;
build(lson), build(rson);
} void add(int now, int v) {
ver[now] = max(ver[now], v);
maxx[now] = max(maxx[now], ver[now] + len[now]);
}
void pushup(int now) {
maxx[now] = max(maxx[now], max(maxx[ls], maxx[rs]));
}
void pushdown(int now) {
add(rs, ver[now]);
add(ls, ver[now] + len[rs]);
} int que(int l, int r, int now, int ln, int rn) {
if(l > rn || r < ln) return 0;
if(l >= ln && r <= rn) return maxx[now];
int mid = (l + r) >> 1;
pushdown(now);
return max(que(lson, ln, rn), que(rson, ln, rn));
}
void modi(int l, int r, int now, int ln, int rn, int v) {
if(l > rn || r < ln) return;
if(l >= ln && r <= rn) {
add(now, v);
return;
}
int mid = (l + r) >> 1;
pushdown(now);
modi(lson, ln, rn, v + min(max(rn - mid, 0), len[rs]));
modi(rson, ln, rn, v);
pushup(now);
}
void modify(int r, int v) {
modi(1, n, 1, r - v + 1, r, 0);
}
int query(int l, int r) {
return que(1, n, 1, l, r);
}
} Seg; int main() {
// freopen("string_example_3.in", "r", stdin); freopen("zz.out", "w", stdout);
n = read(), m = read();
scanf("%s", s + 1);
for(int i = 1; i <= n; i++) insert(i, s[i] - 'a');
for(int i = 2; i <= cnt; i++) to[fa[i]].push_back(i);
dfs(1);
for(int i = 1; i <= m; i++) que[i].l = read(), que[i].r = read(), que[i].max = i;
sort(note + 1, note + tp + 1);
// puts(s + 1);
// for(int i = 1; i <= tp; i++) {
// cerr<< note[i].l << " " << note[i].r << " " << note[i].max << "\n";
// }
// cerr << tp << "\n";
sort(que + 1, que + m + 1);
int tp1 = 1, tp2 = 1;
Seg.build(1, n, 1);
for(int i = 1; i <= n; i++) {
while(tp1 <= tp && note[tp1].r <= i) {
Seg.modify(note[tp1].l, note[tp1].max);
tp1++;
}
while(tp2 <= m && que[tp2].r <= i) {
ans[que[tp2].max] = Seg.query(que[tp2].l, que[tp2].r);
tp2++;
}
}
for(int i = 1; i <= m; i++) cout << ans[i] << "\n";
return 0;
}

Problem C: 重复子串(string)的更多相关文章

  1. POJ 1743 (后缀数组+不重叠最长重复子串)

    题目链接: http://poj.org/problem?id=1743 题目大意:楼教主の男人八题orz.一篇钢琴谱,每个旋律的值都在1~88以内.琴谱的某段会变调,也就是说某段的数可以加减一个旋律 ...

  2. POJ 1743 Musical Theme (后缀数组,求最长不重叠重复子串)(转)

    永恒的大牛,kuangbin,膜拜一下,Orz 链接:http://www.cnblogs.com/kuangbin/archive/2013/04/23/3039313.html Musical T ...

  3. poj 1743 男人八题之后缀数组求最长不可重叠最长重复子串

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 14874   Accepted: 5118 De ...

  4. hdu_2668 Daydream O(n)求最长不重复子串

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2668 Daydream Time Limit: 2000/1000 MS (Java/Others)  ...

  5. [Jobdu] 题目1530:最长不重复子串

    题目描述: 最长不重复子串就是从一个字符串中找到一个连续子串,该子串中任何两个字符都不能相同,且该子串的长度是最大的. 输入: 输入包含多个测试用例,每组测试用例输入一行由小写英文字符a,b,c... ...

  6. ACdream 1430——SETI——————【后缀数组,不重叠重复子串个数】

    SETI Time Limit: 4000/2000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit Statist ...

  7. POJ3693 Maximum repetition substring —— 后缀数组 重复次数最多的连续重复子串

    题目链接:https://vjudge.net/problem/POJ-3693 Maximum repetition substring Time Limit: 1000MS   Memory Li ...

  8. SPOJ - REPEATS —— 后缀数组 重复次数最多的连续重复子串

    题目链接:https://vjudge.net/problem/SPOJ-REPEATS REPEATS - Repeats no tags  A string s is called an (k,l ...

  9. [LeetCode] Longest Substring Without Repeating Characters 最长无重复子串

    Given a string, find the length of the longest substring without repeating characters. For example, ...

随机推荐

  1. 数据分析---SQL(Access数据库)

    1. SQL(Structure Quest Language) 一种结构化查询语言,它是一种通用的关系型数据库操作语言,用于存取数据,查询,更新和管理数据库. 2. 基本语句 Select, Cre ...

  2. MapServer Tutorial——MapServer7.2.1教程学习(大纲)

    MapServer Tutorial——MapServer7.2.1教程学习(大纲) 前言 最近在学习Gis方面的知识,因为电脑硬件配置偏低,顾选择MapServer入手.网上搜索MapServer系 ...

  3. JQ 查找 两个同辈元素之间 的同辈元素 nextUntil() 用于做一个多级菜单

    可以应用的地方,参考了淘宝的API菜单列表 我自己的应用

  4. manjaro配置

    manjaro配置 Table of Contents manjaro配置 系统 一.初次使用 二.安装软件 输入法 emacs samba 三.配置修改 konsole shell颜色 系统 man ...

  5. String 类型equals方法和int == 方法效率比较

    最近写了一个递归方法,在进行比较判断的时候,因为都是integer类型,而integer类型在大于127或者小于-128时会在新建一个,这是因为integer类型的拆装箱机制, 之前没有考虑过equa ...

  6. Tex_安装_在Ubuntu系统下

    $\LaTeX$是一个强大的排版软件,在数学公式.表格.甚至是科学绘图方面有着独特优势.本文在Ubuntu系统下,整理Tex安装相关的操作,以为备忘.所引链接都未同作者商量,如有不妥望及时告知. 命令 ...

  7. 判断是不是微信浏览器和QQ内置浏览器

    is_weixn() { let ua = navigator.userAgent.toLowerCase(); if (ua.match(/MicroMessenger/i) == "mi ...

  8. 3.3 unittest批量执行

    3.3 unittest批量执行 我们在写用例的时候,单个脚本的用例好执行,那么多个脚本的时候,如何批量执行呢?这时候就需要用到unittet里面的discover方法来加载用例了.加载用例后,用un ...

  9. spring boot 项目无法访问静态页面

  10. 常见模块(二) logging模块

    logging模块是专门做日志系统的.分为函数版和自定义函数. (一)logging模块初级版 缺点,不能指定字符集,不能把屏幕输出和文件日志同时记录.只能选择其一. 文件记录日志 import lo ...