Problem C: 重复子串(string)
/*
一个性质? 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)的更多相关文章
- POJ 1743 (后缀数组+不重叠最长重复子串)
题目链接: http://poj.org/problem?id=1743 题目大意:楼教主の男人八题orz.一篇钢琴谱,每个旋律的值都在1~88以内.琴谱的某段会变调,也就是说某段的数可以加减一个旋律 ...
- POJ 1743 Musical Theme (后缀数组,求最长不重叠重复子串)(转)
永恒的大牛,kuangbin,膜拜一下,Orz 链接:http://www.cnblogs.com/kuangbin/archive/2013/04/23/3039313.html Musical T ...
- poj 1743 男人八题之后缀数组求最长不可重叠最长重复子串
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 14874 Accepted: 5118 De ...
- hdu_2668 Daydream O(n)求最长不重复子串
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2668 Daydream Time Limit: 2000/1000 MS (Java/Others) ...
- [Jobdu] 题目1530:最长不重复子串
题目描述: 最长不重复子串就是从一个字符串中找到一个连续子串,该子串中任何两个字符都不能相同,且该子串的长度是最大的. 输入: 输入包含多个测试用例,每组测试用例输入一行由小写英文字符a,b,c... ...
- ACdream 1430——SETI——————【后缀数组,不重叠重复子串个数】
SETI Time Limit: 4000/2000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit Statist ...
- POJ3693 Maximum repetition substring —— 后缀数组 重复次数最多的连续重复子串
题目链接:https://vjudge.net/problem/POJ-3693 Maximum repetition substring Time Limit: 1000MS Memory Li ...
- SPOJ - REPEATS —— 后缀数组 重复次数最多的连续重复子串
题目链接:https://vjudge.net/problem/SPOJ-REPEATS REPEATS - Repeats no tags A string s is called an (k,l ...
- [LeetCode] Longest Substring Without Repeating Characters 最长无重复子串
Given a string, find the length of the longest substring without repeating characters. For example, ...
随机推荐
- Java WEB ----- 文件的上传
最近学到的web阶段的文件的上传,就想记录一下,帮助自己复习以及帮助大家学习,一般我都会把上传的文件存到服务器中的web-inf 下面,因为这样用户不会直接访问到,我们存到数据库的一般都是路径.这里没 ...
- python 多个脚本
1.增删改查haproxy.conf配置文件 1.查询输入:www.oldboy1.com 2.删除输入:{'backend': 'www.oldboy2.org','record':{'server ...
- Centos7配置TiDB集群
一:各模块属性 模块名称 状态 建议实例数 功能 负载均衡组件 TiDB 无状态 2 接收SQL请求,处理SQL相关逻辑,并通过PB找到存储数据的TiKV地址 LVS.HAProxy.F5 PB 集群 ...
- Python中异常处理
高级语言通常都配置了一套try...except...finally的错误处理机制. 1.我们先看一个try的机制 try: res=1/0except ZeroDivisionError as e: ...
- Android:进程优先级
进程优先级 优先级 服务 说明 高优先级 前台进程 ①该进程包含正在与用户进行交互的界面组件,比如一个Activity. ②进程服务被Activity调用,而且这个Activity正在与用户进行交互 ...
- python自学第7天,函数,参数
函数:逻辑结构化和过程化的一种编程方法 面向对象--->类 class 面向过程--->过程 def 函数编程--->函数def import time def logger(): ...
- 【转】20-TCP 协议(滑动窗口——基础)
https://blog.csdn.net/q1007729991/article/details/70142341 相信大家都遇到过这样的场景: 同学 Luffy 给你打电话,让你记下一串手机号码, ...
- Gym - 100783G:Playing With Geometry (几何 离散化 )
pro:给定规则的多边形,规则是指顶点都在整点上,而且是相互垂直的边的交点. 现在给定两个多边形A,B,问A,B缩小,旋转后是否可以变为同一个图形. sol:缩小的话,直接离散化即可,就可以去掉没用的 ...
- 同一台电脑中同时安装oracle database 服务器端和oracle client 客户端时注意
如果在一台电脑中同时安装oracle的客户端和服务器端软件, 一定要先安装oracle database 服务端,并进行相应的配置 listener.ORA. 然后再去安装oracle client ...
- Java_IO异常处理方式_入门小笔记
package IO; import java.io.FileWriter; import java.io.IOException; /** * IO异常处理方式 */ class FileWrite ...