luogu P4482 [BJWC2018] 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 的四种求法 - 后缀数组的更多相关文章
- luogu P4482 [BJWC2018]Border 的四种求法
luogu 对于每个询问从大到小枚举长度,哈希判断是否合法,AC 假的(指数据) 考虑发掘border的限制条件,如果一个border的前缀部分的末尾位置位置\(x(l\le x < r)\)满 ...
- 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree
原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...
- [BJWC2018]Border 的四种求法(后缀自动机+链分治+线段树合并)
题目描述 给一个小写字母字符串 S ,q 次询问每次给出 l,r ,求 s[l..r] 的 Border . Border: 对于给定的串 s ,最大的 i 使得 s[1..i] = s[|s|-i+ ...
- [BJWC2018]Border 的四种求法
description luogu 给一个小写字母字符串\(S\),\(q\)次询问每次给出\(l,r\),求\(s[l..r]\)的\(Border\). solution 我们考虑转化题面:给定\ ...
- 【LuoguP4482】[BJWC2018]Border 的四种求法
题目链接 题意 区间 boder \(n,q\leq 2*10^5\) Sol (暴力哈希/SA可以水过) 字符串区间询问问题,考虑用 \(SAM\) 解决. boder相当于是询问区间 \([l,r ...
- 「BJWC2018」Border 的四种求法
「BJWC2018」Border 的四种求法 题目描述 给一个小写字母字符串 \(S\) ,\(q\) 次询问每次给出 \(l,r\) ,求 \(s[l..r]\) 的 Border . \(1 \l ...
- 【洛谷4482】Border的四种求法(后缀自动机_线段树合并_链分治)
这题我写了一天后交了一发就过了我好兴奋啊啊啊啊啊啊 题目 洛谷 4482 分析 这题明明可以在线做的,为什么我见到的所有题解都是离线啊 -- 什么时候有机会出一个在线版本坑人. 题目的要求可以转化为求 ...
- spring的依赖注入的四种方式,数组与集合注入;引用注入;内部bean注入
三种注入方式 第一种: 基于构造函数 hi.java (bean) package test_one; public class hi { private String name; public hi ...
- c语言 四种方法调用数组
#include <stdio.h> /********************************* * 方法1: 第一维的长度可以不指定 * * 但必须指定第二维的长度 * * ...
随机推荐
- python摸爬滚打之----tcp协议的三次握手四次挥手
TCP协议的三次握手, 四次挥手 三次握手过程 1, 服务器时刻准备接受客户端进程的连接请求, 此时服务器就进入了LISTEN(监听)状态; 2, 客户端进程然后向服务器发出连接请求报文, 之后客户端 ...
- awk 实战
awk 一些好玩的用法.有什么不错的点子可以留言,发挥出awk牛逼功能 分离mac地址 ifconfig wlan0 | grep eth | awk '{n=split($2,arr,": ...
- iOS 控制台po不出值
本人这几天开发项目时在控制台用po命令打印时,发现总是打印不出来,这里将我的解决方案推荐给大家 方法一:(本人就是用该方法解决了问题的) 在控制台选择All Output 方法二: 按图中指示选择de ...
- ArcGIS为面要素生成邻接矩阵
1. 分析工具——>空间关联 使用注意,直接用FID似乎不可行,我是自己重新建了一个"String"字段,值用字段计算器从FID获取过来.之后按照上面的步骤才成功. 实现主要 ...
- 安全相关及HttpClient
1,Spring Security入门示例 Spring Security Annotation Configuration Example – HelloWorld 2,程序模块Get请求,获取响应 ...
- Java bean 转 Map
Java bean 转 Map 时需要使用Fastjson //方法 一 Map<String, Object> a = (Map<String, Object>)JSON.t ...
- xamarin.forms 动态条件更换数据模板
解决方案1: https://oren.codes/2014/12/31/datatemplateselector-for-xamarin-forms/ 解决方案2: https://docs.m ...
- C# Json解析Json = "{\"EX_RETURN\":[{\"MATNR\":\"test\"}] }";
string jtext = "{\"jiangsu\":[{\"wuxi\":\"无锡\"},{\"suzhou\&q ...
- apache----------在apache环境下安装https支持
1.安装mod_ssl yum install mod_ssl2.修改阿帕奇的配置文件开启3.防火墙要开启443端口4.要把三个证书上传到阿帕奇配置文件下.5.更新 httpd.conf 配置文件 ...
- xpath详细讲解
什么是XML XML 指可扩展标记语言(EXtensible Markup Language) XML 是一种标记语言,很类似 HTML XML 的设计宗旨是传输数据,而非显示数据 XML 的标签需要 ...