题目传送门

  传送门

题目大意

  区间border。

  照着金策讲稿做。

Code

 /**
* luogu
* Problem#P4482
* Accepted
* Time: 8264ms
* Memory: 37924k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean; template <typename T>
void pfill(T* pst, const T* ped, T val) {
for ( ; pst != ped; *(pst++) = val);
} const int N = 2e5 + ;
const int bzmax = ;
const signed int inf = (signed) (~0u >> ); typedef class SparseTable {
public:
int n;
int *ar;
int log2[N];
int f[N][bzmax]; SparseTable() { } void init(int n, int* ar) {
this->n = n;
this->ar = ar;
log2[] = ;
for (int i = ; i <= n; i++)
log2[i] = log2[i >> ] + ;
for (int i = ; i < n; i++)
f[i][] = ar[i];
for (int j = ; j < bzmax; j++)
for (int i = ; i + ( << j) - < n; i++)
f[i][j] = min(f[i][j - ], f[i + ( << (j - ))][j - ]);
} int query(int l, int r) {
int d = log2[r - l + ];
return min(f[l][d], f[r - ( << d) + ][d]);
}
} SparseTable; typedef class Pair3 {
public:
int x, y, id; Pair3() { }
Pair3(int x, int y, int id):x(x), y(y), id(id) { }
} Pair3; typedef class SuffixArray {
protected:
Pair3 T1[N], T2[N];
int cnt[N]; public:
int n;
char *str;
int sa[N], rk[N], hei[N];
SparseTable st; void set(int n, char* str) {
this->n = n;
this->str = str;
memset(sa, , sizeof(sa));
memset(rk, , sizeof(rk));
memset(hei, , sizeof(hei));
} void radix_sort(Pair3* x, Pair3* y) {
int m = max(n, );
memset(cnt, , sizeof(int) * m);
for (int i = ; i < n; i++)
cnt[x[i].y]++;
for (int i = ; i < m; i++)
cnt[i] += cnt[i - ];
for (int i = ; i < n; i++)
y[--cnt[x[i].y]] = x[i]; memset(cnt, , sizeof(int) * m);
for (int i = ; i < n; i++)
cnt[y[i].x]++;
for (int i = ; i < m; i++)
cnt[i] += cnt[i - ];
for (int i = n - ; ~i; i--)
x[--cnt[y[i].x]] = y[i];
} void build() {
for (int i = ; i < n; i++)
rk[i] = str[i];
for (int k = ; k <= n; k <<= ) {
for (int i = ; i + k < n; i++)
T1[i] = Pair3(rk[i], rk[i + k], i);
for (int i = n - k; i < n; i++)
T1[i] = Pair3(rk[i], , i);
radix_sort(T1, T2);
int diff = ;
rk[T1[].id] = ;
for (int i = ; i < n; i++)
rk[T1[i].id] = (T1[i].x == T1[i - ].x && T1[i].y == T1[i - ].y) ? (diff) : (++diff);
if (diff == n)
break;
}
for (int i = ; i < n; i++)
sa[--rk[i]] = i;
} void get_height() {
for (int i = , j, k = ; i < n; i++, (k) ? (k--) : ()) {
if (rk[i]) {
j = sa[rk[i] - ];
while (i + k < n && j + k < n && str[i + k] == str[j + k]) k++;
hei[rk[i]] = k;
}
}
} void init_st() {
st.init(n, hei);
} int lcp(int x1, int x2) {
if (x1 == x2)
return n - x1 + ;
x1 = rk[x1], x2 = rk[x2];
if (x1 > x2)
swap(x1, x2);
return st.query(x1 + , x2);
} int compare(int l1, int r1, int l2, int r2) {
int len_lcp = lcp(l1, l2);
int len1 = r1 - l1 + , len2= r2 - l2 + ;
if (len_lcp >= len1 && len_lcp >= len2)
return ;
if (len_lcp < len1 && len_lcp < len2)
return (str[l1 + len_lcp] < str[l2 + len_lcp]) ? (-) : ();
return (len_lcp >= len1) ? (-) : ();
} int query(int u, int v) { // u, v -> sa
if (u == v)
return n - sa[u];
return st.query(u + , v);
} const int& operator [] (int p) {
return sa[p];
} const int& operator () (int p) {
return hei[p];
}
} SuffixArray; namespace IPM { // Internal Pattern Matching typedef class MatchingData {
public:
int a0, a1;
int amount; MatchingData() : amount() { }
explicit MatchingData(int a0) : a0(a0), a1(a0), amount() { }
MatchingData(int a0, int a1) : a0(a0), a1(a1), amount( + (a0 != a1)) { }
MatchingData(int a0, int a1, int amount) : a0(a0), a1(a1), amount(amount) { }
MatchingData(int* a, int amount) : amount(amount) {
if (amount == )
return;
if (amount == )
a0 = a1 = a[];
else if (amount >= ) {
a0 = a[], a1 = a[];
int d = a1 - a0;
for (int i = ; i < amount; i++)
if (a[i] - a[i - ] != d)
assert(false);
}
} boolean included(int x) {
if (!amount)
return false;
boolean aflag = (x == a0 || x == a1);
if (amount <= || aflag)
return aflag;
x -= a0;
int d = a1 - a0;
return (!(x % d) && (x / d >= && x / d < amount));
} int indexOf(int x) {
if (!included(x))
return -;
return (x - a0) / (a1 - a0);
} int last() {
return value(amount - );
} int value(int n) {
return a0 + (a1 - a0) * n;
} int dif() {
return a1 - a0;
} MatchingData operator - () {
return MatchingData(-a0, -a1, amount);
} MatchingData operator + (int d) {
return MatchingData(a0 + d, a1 + d, amount);
} MatchingData operator - (int d) {
return MatchingData(a0 - d, a1 - d, amount);
} MatchingData operator ~ () {
if (amount <= )
return *this;
int _a0 = value(amount - );
int _a1 = value(amount - );
return MatchingData(_a0, _a1, amount);
} MatchingData operator & (MatchingData b) {
static int tmp[];
if (!amount || !b.amount)
return MatchingData();
if (amount < ) {
int tp = ;
for (int i = , x = a0, d = a1 - a0; i < amount; i++, x += d) {
if (b.included(x)) {
tmp[tp++] = x;
}
}
return MatchingData(tmp, tp);
}
if (b.amount < ) {
int tp = ;
for (int i = , x = b.a0, d = b.a1 - b.a0; i < b.amount; i++, x += d) {
if (included(x)) {
tmp[tp++] = x;
}
}
return MatchingData(tmp, tp);
}
int d = a1 - a0;
assert(d == b.a1 - b.a0);
int l = indexOf(b.a0), r = l + b.amount;
if (l == -)
return MatchingData();
l = max(l, );
r = min(amount, r);
if (l >= r)
return MatchingData();
return MatchingData(value(l), value(l + ), r - l);
}
} MatchingData; int n;
char* str;
//int *log2;
SuffixArray sa;
int f[bzmax][N]; inline void init(char* str, int _n) {
// log2 = new int[(n + 1)];
// log2[0] = -1;
// for (int i = 1; i <= n; i++)
// log2[i] = log2[i >> 1] + 1;
n = _n;
sa.set(n, str);
sa.build();
sa.get_height();
sa.init_st();
for (int k = ; ( << k) <= n; k++) {
int* F = f[k], len = ( << k);
for (int i = ; i + len <= n; i++)
F[i] = i;
sort(F, F + (n - len) + , [&] (const int& x, const int& y) {
int rt = sa.compare(x, x + len - , y, y + len - );
if (!rt)
return x < y;
return rt == -;
}); // it can be replace by radix sort
}
} pair<int, int> getRange(int s, int k) {
int len = << k, l = , r = n - len, mid;
int* F = f[k], L, R;
while (l <= r) {
mid = (l + r) >> ;
if (sa.compare(s, s + len - , F[mid], F[mid] + len - ) == )
l = mid + ;
else
r = mid - ;
}
L = r + ;
l = , r = n - len;
while (l <= r) {
mid = (l + r) >> ;
if (sa.compare(s, s + len - , F[mid], F[mid] + len - ) >= )
l = mid + ;
else
r = mid - ;
}
R = l - ;
return pair<int, int>(L, R);
} int succ(int s, int k, int i, int L, int R) { // pos >= i
int len = << k, l = , r = n - len;
int mid;
int *F = f[k];
if (L > R)
return inf;
l = L, r = R;
while (l <= r) {
mid = (l + r) >> ;
if (F[mid] >= i)
r = mid - ;
else
l = mid + ;
}
if (r == R)
return inf;
return F[r + ];
} int pred(int s, int k, int i) { //<= i
int len = << k, l = , r = n - len;
int L, R, mid;
int *F = f[k];
while (l <= r) {
mid = (l + r) >> ;
if (sa.compare(s, s + len - , F[mid], F[mid] + len - ) == )
l = mid + ;
else
r = mid - ;
}
L = r + ;
l = , r = n - len;
while (l <= r) {
mid = (l + r) >> ;
if (sa.compare(s, s + len - , F[mid], F[mid] + len - ) >= )
l = mid + ;
else
r = mid - ;
}
R = l - ;
if (L > R)
return -;
l = L, r = R;
while (l <= r) {
mid = (l + r) >> ;
if (F[mid] <= i)
l = mid + ;
else
r = mid - ;
}
if (l == L)
return -;
return F[l - ];
} // rt - lt + 1 = 2 ^ k
MatchingData query(int ls, int rs, int lt, int k) {
int len = << k;
pair<int, int> range = getRange(lt, k);
int a0 = succ(lt, k, ls, range.first, range.second);
if (a0 + len - > rs)
return MatchingData();
int a1 = succ(lt, k, a0 + , range.first, range.second);
if (a1 + len - > rs)
return MatchingData(a0);
int an = pred(lt, k, rs - len + );
assert(an >= ls);
MatchingData rt (a0, a1);
rt.amount = N;
rt.amount = rt.indexOf(an) + ;
return rt;
} } using IPM :: MatchingData; int n, m;
char str[N]; inline void init() {
scanf("%s", str);
n = strlen(str);
IPM :: init(str, n);
} int query(int l, int r) {
int t = , half_len = (r - l + ) >> ;
while (( << t) < half_len)
t++;
for (int i = t; ~i; i--) {
int len = min(r - l, << (i + )), hlen = ( << i);
MatchingData md_l = IPM :: query(l, l + len - , r - hlen + , i);
MatchingData md_r = IPM :: query(r - len + , r, l, i);
md_l = md_l - l + hlen;
md_r = -(~md_r) + (r + );
md_l = md_l & md_r;
if (md_l.amount)
return md_l.last();
}
return (str[l] == str[r] && l < r);
} inline void solve() {
scanf("%d", &m);
int l, r;
while (m--) {
scanf("%d%d", &l, &r);
printf("%d\n", query(--l, --r));
}
} int main() {
// freopen("border.in", "r", stdin);
// freopen("border.out", "w", stdout);
init();
solve();
return ;
}

luogu P4482 [BJWC2018] Border 的四种求法 - 后缀数组的更多相关文章

  1. luogu P4482 [BJWC2018]Border 的四种求法

    luogu 对于每个询问从大到小枚举长度,哈希判断是否合法,AC 假的(指数据) 考虑发掘border的限制条件,如果一个border的前缀部分的末尾位置位置\(x(l\le x < r)\)满 ...

  2. 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree

    原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...

  3. [BJWC2018]Border 的四种求法(后缀自动机+链分治+线段树合并)

    题目描述 给一个小写字母字符串 S ,q 次询问每次给出 l,r ,求 s[l..r] 的 Border . Border: 对于给定的串 s ,最大的 i 使得 s[1..i] = s[|s|-i+ ...

  4. [BJWC2018]Border 的四种求法

    description luogu 给一个小写字母字符串\(S\),\(q\)次询问每次给出\(l,r\),求\(s[l..r]\)的\(Border\). solution 我们考虑转化题面:给定\ ...

  5. 【LuoguP4482】[BJWC2018]Border 的四种求法

    题目链接 题意 区间 boder \(n,q\leq 2*10^5\) Sol (暴力哈希/SA可以水过) 字符串区间询问问题,考虑用 \(SAM\) 解决. boder相当于是询问区间 \([l,r ...

  6. 「BJWC2018」Border 的四种求法

    「BJWC2018」Border 的四种求法 题目描述 给一个小写字母字符串 \(S\) ,\(q\) 次询问每次给出 \(l,r\) ,求 \(s[l..r]\) 的 Border . \(1 \l ...

  7. 【洛谷4482】Border的四种求法(后缀自动机_线段树合并_链分治)

    这题我写了一天后交了一发就过了我好兴奋啊啊啊啊啊啊 题目 洛谷 4482 分析 这题明明可以在线做的,为什么我见到的所有题解都是离线啊 -- 什么时候有机会出一个在线版本坑人. 题目的要求可以转化为求 ...

  8. spring的依赖注入的四种方式,数组与集合注入;引用注入;内部bean注入

    三种注入方式 第一种: 基于构造函数 hi.java (bean) package test_one; public class hi { private String name; public hi ...

  9. c语言 四种方法调用数组

      #include <stdio.h> /********************************* * 方法1: 第一维的长度可以不指定 * * 但必须指定第二维的长度 * * ...

随机推荐

  1. 来自一个电子狂的stm32学习历程

    文章尾部有学习时的一些视频资料在学的可以看看那么我们就进入今天的主题我stm32的学习历程 在学习了51单片机之后,早已经对单片机这个东西甚有了解了,所有不管是从内部资源,还是一些常见应用,都可以说的 ...

  2. cnblogs

    想注册个博客园来着的,看着大佬们的博客都十分漂亮,但是发现我因为太菜没有办法搞定美化问题. 以后再说吧 写写东西,反正也没人看,但是写的时候尽量按给别人看的格式写吧 2019.3.15 开通博客 计划 ...

  3. python练习题-day21

    1.三级菜单 china_ditie = { "北京": { "一号线": ["四惠", "大望路", "天安 ...

  4. 清除eclipse项目中没用的图片、js、css代码

    import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOExce ...

  5. SqlServer 字段拼接

    最近入职了新公司,使用的是sql server 之前因为一直使用的都是Mysql,mysql 有专用的GROUP_CONCAT()函数,那么这个就是很方便的啦,只要对结果集进行一个Group By  ...

  6. gRPC 在 Python中的应用

    python -m grpc_tools.protoc --proto_path=. --python_out=. --grpc_python_out=. hello.proto 简介 在python ...

  7. Fiddler抓包【2】_捕获设置

    1.Fiddler抓web网站请求 手动设置方法一:Tools--->WinINET Options--->连接--->局域网设置--->代理服务器勾选后“高级”---> ...

  8. STM32F103单片机解密资料

    STM32F103单片机解密资料下载 一.STM32 32位ARM Cortex MCU 基于ARM® Cortex® M 处理器内核的 32位闪存微控制器STM32产品家族,为MCU用户开辟了一个全 ...

  9. windows之电脑开机出现 this product is covered by one or more of the following prtents

    电脑开机出现 this product is covered by one or more of the following prtents 有次意外断电后就每次都出现这个提示,然后要等检查完才能进入 ...

  10. package.json中 npm依赖包版本前的符号的意义

    版本的格式 major.minor.patch 主版本号.次版本号.修补版本号 ———————————————————— patch:修复bug,兼容老版本 minor:新增功能,兼容老版本 majo ...