luogu P5310 [Ynoi2011] 遥远的过去
https://www.luogu.com.cn/problem/P5310
对于这种要离散化,再匹配的一般的字符串算法都不好处理
考虑哈希
显然可以在splay上维护每个位置都hash值
h a = ∑ p o s [ i ] ∗ B r a n k [ i ] ha=\sum pos[i]*B^{rank[i]} ha=∑pos[i]∗Brank[i]
对于A每个长度为m的子串都把哈希值求出来扔到哈希表里
然后再拿splay维护B的哈希值即可
直接在哈希表里找
code:
#include<bits/stdc++.h>
#define N 200050
#define ls ch[x][0]
#define rs ch[x][1]
#define ll unsigned long long
using namespace std;
int size[N], ch[N][2], fa[N], root, v[N], n, m, q;
ll ha[N], mi[N], S;
const ll B = 11117;
const ll mod = 100003;
void update(int x) {
size[x] = size[ls] + size[rs] + 1;
ha[x] = ha[ls] + mi[size[ls]] * (ll)x + mi[size[ls] + 1] * ha[rs];
}
int get(int x) {
return ch[fa[x]][1] == x;
}
void rotate(int x) {
int f = fa[x], gf = fa[f], k = get(x);
if(!f) return ;
if(gf) ch[gf][get(f)] = x; fa[x] = gf;
ch[f][k] = ch[x][!k], fa[ch[x][!k]] = f;
ch[x][!k] = f, fa[f] = x;
update(f), update(x);
}
inline void splay(int x) {
int f = fa[x];
while(f) {
if(fa[f]) rotate(get(x) == get(f)? f : x);
rotate(x);
f = fa[x];
// printf("%d %d\n", x, f);
}
root = x;
}
void insert(int &x, int id, int f) {
// printf("%d %d %d \n", x, id, f);
if(!x) {x = id; fa[x] = f; update(x); splay(x); return ;}
if(v[id] < v[x]) insert(ls, id, x);
else insert(rs, id, x);
}
void clear(int x) {
fa[x] = ls = rs = size[x] = 0;
}
void del(int x) {
splay(x);
if(!ls || !rs) {root = ls + rs; fa[root] = 0; clear(x); return ; }
int now = ls;
while(ch[now][1]) now = ch[now][1];
splay(now);
ch[now][1] = ch[x][1], fa[ch[x][1]] = now;
clear(x); update(now);
}
void deb(int x) {
if(!x) return ;
deb(ls);
printf(" %d %d %d ", x, ls, rs);
deb(rs);
}
struct HAT {
int nxt, s;
ll val;
} e[N << 1];
int p[N], eid;
void init() {
memset(p, -1, sizeof p);
eid = 0;
}
void INS(ll x) {
int u = x % mod;
for(int i = p[u]; i + 1; i = e[i].nxt) {
if(x == e[i].val) { ++ e[i].s; return ;}
}
e[eid].val = x, e[eid].s = 1, e[eid].nxt = p[u];
p[u] = eid ++;
}
int QRY(ll x) {
int u = x % mod;
for(int i = p[u]; i + 1; i = e[i].nxt) {
if(x == e[i].val) return e[i].s;
} return 0;
}
int main() {
init();
scanf("%d%d%d", &n ,&m, &q);
mi[0] = 1;
for(int i = 1; i <= n; i ++) mi[i] = mi[i - 1] * B;
for(int i = 1; i <= n; i ++) scanf("%d", &v[i]);
for(int i = 1; i <= m; i ++) insert(root, i, 0), S += mi[i - 1];
for(int i = m; i <= n; i ++) {
INS(ha[root] - S * (i - m));
// printf("\n ** %llu ", ha[root]); deb(root); printf("\n");
del(i - m + 1);
// printf("\n ** "); deb(root); printf("\n");
insert(root, i + 1, 0);
}
root = 0;
memset(ch, 0, sizeof ch), memset(fa, 0, sizeof fa);
for(int i = 1; i <= m; i ++) scanf("%d", &v[i]), insert(root, i, 0);
while(q --) {
int x, y;
scanf("%d%d", &x, &y);
del(x);
v[x] = y; insert(root, x, 0);
printf("%d\n", QRY(ha[root]));
}
return 0;
}