[题目链接]

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. 前端模板inspinia

    前端模板,可以下个免费的,可以花点小钱买.或者github搜索一个 https://chuibility.github.io/inspinia/ http://cn.inspinia.cn/layou ...

  2. OpenSceneGraph FAQ 【转】

    1.地球背面的一个点,计算它在屏幕上的坐标,能得到吗? 不是被挡住了吗? 答:计算一个空间点的屏幕坐标,使用osgAPEx::GetScreenPosition函数.当空间点处于相机视空间内(不管它是 ...

  3. 【Hibernate步步为营】--核心对象+持久对象全析(三)

    上篇文章讨论了Hibernate持久对象的生命周期,在整个生命周期中一个对象会经历三个状态,三种状态的转换过程在开发过程中是可控的.并且是通过用法来控制它们的转化过程.详细的转化过程今天就来着重讨论下 ...

  4. 【足迹C++primer】39、动态内存与智能指针(3)

    动态内存与智能指针(3) /** * 功能:动态内存与智能指针 * 时间:2014年7月8日15:33:58 * 作者:cutter_point */ #include<iostream> ...

  5. c#打包文件解压缩 C#中使用委托、接口、匿名方法、泛型委托实现加减乘除算法 一个简单例子理解C#的协变和逆变 对于过长字符串的大小比对

    首先要引用一下类库:using Ionic.Zip;这个类库可以到网上下载. 下面对类库使用的封装方法: 得到指定的输入流的ZIP压缩流对象 /// <summary> /// 得到指定的 ...

  6. PHP ORM操作MySQL数据库

    ORM----Oriented Relationship Mapper,即用面向对象的方式来操作数据库.归根结底,还是对于SQL语句的封装. 首先,我们的数据库有如下一张表: 我们希望能够对这张表,利 ...

  7. fping - send ICMP ECHO_REQUEST packets to network hosts

    NAME fping - send ICMP ECHO_REQUEST packets to network hosts SYNOPSIS fping [ options ] [ systems... ...

  8. Android录屏命令、Android录Gif、Android录视频

    NoHttp开源地址:https://github.com/yanzhenjie/NoHttp NoHttp具体使用文档已公布,你想知道的全都有,请点我移步! 版权声明:转载请注明本文转自严振杰的博客 ...

  9. 基于multiprocessing和threading实现非阻塞的GUI界面显示

    ========================================================= 环境:python2.7.pyqt4.eric16.11 热点:multiproce ...

  10. Android Studio 工程的 .gitignore

    新建一个 Android Studio 工程时会默认建立两个 .gitignore 文件 .gitignore *.iml .gradle /local.properties /.idea/works ...