[TJOI2016 & HEOI2016] 字符串
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=4556
[算法]
不难发现 , 对于每个询问
ans = max{ min{b - i + 1 , lcp(i , c) } (a <= i <= b)
不妨二分答案mid , 那么问题就转化为求 max{ lcp(i , c) } (a <= i <= b - mid + 1)
而我们知道 , 所有lcp(i , j) <= k的i是连续的一段区间
可以再次通过二分求出这个区间
问题又转化为判断[a , b - mid + 1]中是否有rank值在区间[L , R]中的数
构建出后缀数组 , 主席树维护rank值即可
时间复杂度 : O(NlogN ^ 2)
[代码]
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + ;
const int MAXLOG = ;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull; #define rint register int int n , m;
int rk[N] , rt[N] , sa[N] , cnt[N] , height[N] , lg[N];
int val[N][MAXLOG];
char s[N]; struct Presitent_Segment_Tree
{
int sz;
int lc[N * ] , rc[N * ] , cnt[N * ];
Presitent_Segment_Tree()
{
sz = ;
}
inline void build(int &now , int l , int r)
{
now = ++sz;
if (l == r) return;
int mid = (l + r) >> ;
build(lc[now] , l , mid);
build(rc[now] , mid + , r);
}
inline void modify(int &now , int old , int l , int r , int x , int value)
{
now = ++sz;
lc[now] = lc[old] , rc[now] = rc[old];
cnt[now] = cnt[old] + value;
if (l == r) return;
int mid = (l + r) >> ;
if (mid >= x) modify(lc[now] , lc[old] , l , mid , x , value);
else modify(rc[now] , rc[old] , mid + , r , x , value);
}
inline bool query(int rt1 , int rt2 , int l , int r , int ql , int qr)
{
if (ql > qr || cnt[rt1] - cnt[rt2] == )
return false;
if (l == ql && r == qr)
return (cnt[rt1] - cnt[rt2] > );
int mid = (l + r) >> ;
if (mid >= qr) return query(lc[rt1] , lc[rt2] , l , mid , ql , qr);
else if (mid + <= ql) return query(rc[rt1] , rc[rt2] , mid + , r , ql , qr);
else return query(lc[rt1] , lc[rt2] , l , mid , ql , mid) | query(rc[rt1] , rc[rt2] , mid + , r , mid + , qr);
}
} PST;
template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
T f = ; x = ;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = (x << ) + (x << ) + c - '';
x *= f;
}
inline void build_sa()
{
static int x[N] , y[N];
memset(cnt , , sizeof(cnt));
for (rint i = ; i <= n; i++) ++cnt[(int)s[i]];
for (rint i = ; i <= ; i++) cnt[i] += cnt[i - ];
for (rint i = n; i >= ; i--) sa[cnt[(int)s[i]]--] = i;
rk[sa[]] = ;
for (rint i = ; i <= n; i++) rk[sa[i]] = rk[sa[i - ]] + (s[sa[i]] != s[sa[i - ]]);
for (rint k = ; rk[sa[n]] != n; k <<= )
{
for (rint i = ; i <= n; i++)
x[i] = rk[i] , y[i] = (i + k <= n) ? rk[i + k] : ;
memset(cnt , , sizeof(cnt));
for (rint i = ; i <= n; i++) ++cnt[y[i]];
for (rint i = ; i <= n; i++) cnt[i] += cnt[i - ];
for (rint i = n; i >= ; i--) rk[cnt[y[i]]--] = i;
memset(cnt , , sizeof(cnt));
for (rint i = ; i <= n; i++) ++cnt[x[i]];
for (rint i = ; i <= n; i++) cnt[i] += cnt[i - ];
for (rint i = n; i >= ; i--) sa[cnt[x[rk[i]]]--] = rk[i];
rk[sa[]] = ;
for (rint i = ; i <= n; i++) rk[sa[i]] = rk[sa[i - ]] + (x[sa[i]] != x[sa[i - ]] || y[sa[i]] != y[sa[i - ]]);
}
}
inline void get_height()
{
int k = ;
for (rint i = ; i <= n; i++)
{
if (k) --k;
int j = sa[rk[i] - ];
while (s[i + k] == s[j + k]) ++k;
height[rk[i]] = k;
}
}
inline void rmq_init()
{
for (rint i = ; i <= n; i++)
val[i][] = height[i];
for (rint j = ; ( << j) <= n; j++)
{
for (rint i = ; i + ( << j) - <= n; i++)
{
val[i][j] = min(val[i][j - ] , val[i + ( << (j - ))][j - ]);
}
}
}
inline int query(int x , int y)
{
if (x > y) return ;
int k = lg[y - x + ];
return min(val[x][k] , val[y - ( << k) + ][k]);
} int main()
{ scanf("%d%d" , &n , &m);
scanf("%s" , s + );
build_sa();
get_height();
rmq_init();
PST.build(rt[] , , n);
for (rint i = ; i <= n; i++) PST.modify(rt[i] , rt[i - ] , , n , rk[i] , );
for (rint i = ; i <= n; i++) lg[i] = (double)(log(i) / log(2.0));
while (m--)
{
int a , b , c , d;
read(a); read(b); read(c); read(d);
int l = , r = min(d - c + , b - a + ) , ans = ;
while (l <= r)
{
int mid = (l + r) >> ;
int ll = , rr = rk[c] - , L = rk[c] , R = rk[c];
while (ll <= rr)
{
int md = (ll + rr) >> ;
if (query(md + , rk[c]) >= mid)
{
L = md;
rr = md - ;
} else ll = md + ;
}
ll = rk[c] + , rr = n , R = rk[c];
while (ll <= rr)
{
int md = (ll + rr) >> ;
if (query(rk[c] + , md) >= mid)
{
R = md;
ll = md + ;
} else rr = md - ;
}
if (PST.query(rt[b - mid + ] , rt[a - ] , , n , L , R))
{
l = mid + ;
ans = mid;
} else r = mid - ;
}
printf("%d\n" , ans);
} return ; }
[TJOI2016 & HEOI2016] 字符串的更多相关文章
- Bzoj 4556: [Tjoi2016&Heoi2016]字符串
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 177 Solved: 92[Sub ...
- Bzoj4556: [Tjoi2016&Heoi2016]字符串 后缀数组
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 169 Solved: 87[Sub ...
- 4556: [Tjoi2016&Heoi2016]字符串
4556: [Tjoi2016&Heoi2016]字符串 链接 分析: 首先可以二分这个长度.此时需要判断是否存在一个以b结尾的前缀,满足与[c,d]的lcp大于等于mid. 如果我们把串翻转 ...
- [BZOJ4556][Tjoi2016&Heoi2016]字符串 后缀数组+主席树
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MB Description 佳媛姐姐过生日的时候,她的小 ...
- 【BZOJ4556】[Tjoi2016&Heoi2016]字符串 后缀数组+二分+主席树+RMQ
[BZOJ4556][Tjoi2016&Heoi2016]字符串 Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一 ...
- [BZOJ4556][TJOI2016&&HEOI2016]字符串(二分答案+后缀数组+RMQ+主席树)
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1360 Solved: 545[S ...
- [BZOJ4556][Tjoi2016&Heoi2016]字符串 主席树+二分+倍增+后缀自动机
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1215 Solved: 484[S ...
- BZOJ4556: [Tjoi2016&Heoi2016]字符串
Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了 一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开 ...
- BZOJ4556 [Tjoi2016&Heoi2016]字符串 SA ST表 二分答案 主席树
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ4556.html 题目传送门 - BZOJ4556 题意 给定一个长度为 $n$ 的字符串 $s$ . ...
- 2019.02.27 bzoj4556: [Tjoi2016&Heoi2016]字符串(二分答案+sam+线段树合并)
传送门 题意:给一个字符串SSS. 有mmm次询问,每次给四个参数a,b,c,da,b,c,da,b,c,d,问s[a...b]s[a...b]s[a...b]的所有子串和s[x...y]s[x... ...
随机推荐
- Keras学习
参加比赛用到了keras,虽然之前用tensorflow,但是感觉tensorflow的确不太友好,api比较难读,然后就学习keras使用 随着深入,发现keras的api确实比较友好 跑了一些ex ...
- css3 - 基本选择器
有人说类选择器最好不要超过三层,其实我也是这样认为的,不是吗? 选择器分为四大类 标签.全选(相对于子类继承了0.1).类.ID 权值分别是:1->0.1->10->100(权值可叠 ...
- Android Camera探究之路——起步
Android Camera探究之路--起步 Camera在手机中有着举足轻重的地位,无论是二维码还是照片.识别.都离不开摄像头,本文将对Android中的Camera进行全面解析. 权限镇楼: &l ...
- C语言变长数组 struct中char data[0]的用法
版权声明:本文为博主原创文章,未经博主允许不得转载. 今天在看一段代码时出现了用结构体实现变长数组的写法,一开始因为忘记了这种技术,所以老觉得作者的源码有误,最后经过我深思之后,终于想起以前看过的用s ...
- Layout规则总结
一.尺寸要求 1.过孔到焊盘的距离多少合适? 6mil左右 2.铜皮到边框的距离多少合适? 极限8mil,通常12,最好做到20,40 3.Thermal焊盘打地孔个数? 正方形 3*3 4*4 ...
- 笔记本POWER部分的应用——(MOS/LDO/BUCK BOOST)
一.MOSFET 简介: 金属-氧化物半导体场效应晶体管,简称金氧半场效晶体管(Metal-Oxide-Semiconductor Field-Effect Transistor, MOSFET)是一 ...
- Linux - D-Bus
http://en.wikipedia.org/wiki/D-Bus D-Bus is a free and open-source inter-process communication (IPC) ...
- IOS UIWebView 随记
UIWebView中加载的网页尺寸太大,如何让网页适应屏幕大小 webview.scalesPageToFit = YES;
- 07 http内容压缩
一:http内容压缩 思考: Content-Length在之前的学习中,我们知道,代表返回的主体的长度 但此处,为什么返回的主体长度和content-length不一致呢? 原因在于: Conten ...
- android lanchmode
http://www.cnblogs.com/xiaoQLu/archive/2012/07/17/2595294.html http://www.cnblogs.com/lwbqqyumidi/p/ ...