[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... ...
随机推荐
- Jmeter Summariser report及其可视化
Jmeter summariser report的设置在:bin/jmeter.properties #------------------------------------------------ ...
- python中 urllib, urllib2, httplib, httplib2 几个库的区别
转载 摘要: 只用 python3, 只用 urllib 若只使用python3.X, 下面可以不看了, 记住有个urllib的库就行了 python2.X 有这些库名可用: urllib, urll ...
- ffmpeg一些filter使用方法、以及一些功能命令
1.加字幕 命令:ffmpeg -i <input> -filter_complex subtitles=filename=<SubtitleName>-y <outpu ...
- C 标准库 - <time.h>
C 标准库 - <time.h> 简介 time.h 头文件定义了四个变量类型.两个宏和各种操作日期和时间的函数. 库变量 下面是头文件 time.h 中定义的变量类型: 序号 变量 &a ...
- 猫猫学iOS之小知识之_xcode插件的删除方法_自己主动提示图片插件KSImageNamed有时不灵_分类或宏之类不能自己主动提示,
猫猫分享,必须精品 原创文章.欢迎转载. 转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243 一:解决解决自己主动提示图片插件KSImageNamed有时不 ...
- python datetime获取几分钟、小时、天之前的时间
import datetime print ((datetime.datetime.now()-datetime.timedelta(days=1)).strftime("%Y-%m-%d ...
- 服务管理-Apache
WEB服务器介绍 web server 有两个意思: 一台负责提供网页的服务器,通过HTTP协议传给客户端(一般是指网页浏览器). 一个提供网页的服务器程序. 常见的WEB服务器 Apache是世界使 ...
- 再过半小时,你就能明白kafka的工作原理了
本文在个人技术博客不同步发布,详情可猛戳 亦可扫描屏幕右侧二维码关注个人公众号,公众号内有个人联系方式,等你来撩... 为什么需要消息队列 周末无聊刷着手机,某宝网APP突然蹦出来一条消息" ...
- caffeModels--models-caffes-大全
caffe的伯克利主页:http://caffe.berkeleyvision.org/caffe的github主页:https://github.com/BVLC/caffe caffe的model ...
- inception安装步骤---自己整理的安装步骤
inception安装步骤---自己整理的安装步骤2015-09-18 15:51 6185人阅读 评论(1) 收藏 举报 分类: inception相关版权声明:本文为博主原创文章,未经博主允许不得 ...