[题目链接]

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] 字符串的更多相关文章

  1. Bzoj 4556: [Tjoi2016&Heoi2016]字符串

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 177  Solved: 92[Sub ...

  2. Bzoj4556: [Tjoi2016&Heoi2016]字符串 后缀数组

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 169  Solved: 87[Sub ...

  3. 4556: [Tjoi2016&Heoi2016]字符串

    4556: [Tjoi2016&Heoi2016]字符串 链接 分析: 首先可以二分这个长度.此时需要判断是否存在一个以b结尾的前缀,满足与[c,d]的lcp大于等于mid. 如果我们把串翻转 ...

  4. [BZOJ4556][Tjoi2016&Heoi2016]字符串 后缀数组+主席树

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MB Description 佳媛姐姐过生日的时候,她的小 ...

  5. 【BZOJ4556】[Tjoi2016&Heoi2016]字符串 后缀数组+二分+主席树+RMQ

    [BZOJ4556][Tjoi2016&Heoi2016]字符串 Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一 ...

  6. [BZOJ4556][TJOI2016&&HEOI2016]字符串(二分答案+后缀数组+RMQ+主席树)

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1360  Solved: 545[S ...

  7. [BZOJ4556][Tjoi2016&Heoi2016]字符串 主席树+二分+倍增+后缀自动机

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1215  Solved: 484[S ...

  8. BZOJ4556: [Tjoi2016&Heoi2016]字符串

    Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了 一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开 ...

  9. BZOJ4556 [Tjoi2016&Heoi2016]字符串 SA ST表 二分答案 主席树

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ4556.html 题目传送门 - BZOJ4556 题意 给定一个长度为 $n$ 的字符串 $s$ . ...

  10. 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... ...

随机推荐

  1. 转:Android IOS WebRTC 音视频开发总结 (系列文章集合)

    随笔分类 - webrtc   Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译和整理的,译 ...

  2. Webduino Smart 从入门到起飞

    前言 原创文章,转载引用务必注明链接.水平有限,如有疏漏,欢迎指正. 试用了一下,感觉这板子+WebduinoBlockly在线开发环境,下限低.上限也低,以后肯定要刷其他固件的.举个简单的例子,WB ...

  3. SQL_字符操作函数

    原创作品.出自 "深蓝的blog" 博客.欢迎转载,转载时请务必注明下面出处,否则追究版权法律责任. 深蓝的blog:http://blog.csdn.net/huangyanlo ...

  4. Odoo MRP 实际成本

    Odoo MRP 8 对于 产成品并不支持 实际成本记账 本人开发了一个模块,支持此特性, 可以在 淘宝店铺 购买 https://item.taobao.com/item.htm?_u=85jr9d ...

  5. C和C++代码精粹笔记1

    CH1 更好的C 运算符重载规定,必须有一个为用户自定义类型 一些输出没注意到的函数: float x = 123.456, y = 12345; //cout.precision(2); //显示两 ...

  6. 我对C语言输入和输出和一些其他的疑惑点

    gets(字符串数组) 用来接收字符串数组 等同于 scanf("%s",字符串数组名)  需要说的一点是 字符串的数组名 就表示数组的第一个元素的地址 所以加不加&取地址 ...

  7. kubectl技巧之通过jsonpath截取属性

    系列目录 前面一节我们介绍了使用go-template截取属性,go-template功能非常强大,可以定义变量,使用流程控制等,这是jsonpath所不具备的.然而,jsonpth使用的时候更为灵活 ...

  8. eclipse 导入web项目时常见错误

    1. JavaWeb:报错信息The superclass "javax.servlet.http.HttpServlet" was not found on the Java B ...

  9. HTML5即将迎来黄金时代 轻应用再成行业焦点

    2015-01-23 11:03:09     来源:快鲤鱼 大众能看到的H5效果拜“微信”所赐,几乎每天都有H5页面的推广以及H5小游戏在微信上传播.其实,H5的大热与百度不无关系,2012年开始, ...

  10. linux中vi编辑器(转载)

    三种模式相互切换 在命令终端输入vi进入vi编辑器. 命令模式:进入编辑器即进入命令模式, 输入模式:在命令模式下输入“i ”进入输入模式: 末行模式:按“:”进入末行模式: 在输入模式切换至末行模式 ...