您的位置:首页 > 其它

[后缀自动机][LCT] BZOJ 2555: SubString

2017-12-23 20:43 357 查看

Solution

出现的次数就是匹配到的点的rightu集合大小。

一个点的|rightu|有变化会对parent树上的祖先造成相应的改变。

因为这题强制在线,所以就用LCT维护|rightv|啦。

#include <bits/stdc++.h>
#define show(x) cerr << #x << " = " << x << endl
using namespace std;
typedef long long ll;
typedef pair<int, int> Pairs;

const int N = 1512121;

inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
template<typename T>
inline void read(T &x) {
static char c; x = 0; int sgn = 0;
for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1;
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
if (sgn) x = -x;
}
inline void read(char *ch) {
char c; int len = 0;
for (c = get(); c < 'A' || c > 'Z'; c = get());
for (; c >= 'A' && c <= 'Z'; c = get()) ch[len++] = c;
ch[len] = 0;
}

namespace LCT {
struct node {
node *ch[2];
node *fa;
int add, key;
inline void Mark(int x) {
add += x; key += x;
}
inline void PushDown(void) {
if (add) {
ch[0]->Mark(add);
ch[1]->Mark(add);
add = 0;
}
}
};
node T
;
node *null;
inline void Init(int n) {
null = T;
null->ch[0] = null->ch[1] = null->fa = null;
null->key = null->add = 0;
for (int i = 1; i <= n; i++) {
T[i].ch[0] = T[i].ch[1] = T[i].fa = null;
T[i].add = T[i].key = 0;
}
}
inline bool IsRoot(node *x) {
return x->fa == null || (x->fa->ch[0] != x && x->fa->ch[1] != x);
}
inline void Rotate(node *x) {
node *y = x->fa, *z = y->fa;
int l = (y->ch[0] != x), r = l ^ 1;
if (!IsRoot(y)) {
if (z->ch[0] == y) z->ch[0] = x;
else z->ch[1] = x;
}
x->fa = z; y->fa = x; x->ch[r]->fa = y;
y->ch[l] = x->ch[r]; x->ch[r] = y;
}
inline void Down(node *x) {
if (!IsRoot(x)) Down(x->fa);
x->PushDown();
}
inline void Splay(node *x) {
Down(x);
while (!IsRoot(x)) {
node *y = x->fa, *z = y->fa;
if (!IsRoot(y)) {
if (y->ch[0] == x ^ z->ch[0] == y) Rotate(x);
else Rotate(y);
}
Rotate(x);
}
}
inline void Access(node *x) {
for (node *y = null; x != null; x = x->fa) {
Splay(x); x->ch[1] = y; y = x;
}
}
inline void Link(node *x, node *y) {
Access(y); Splay(y);
x->fa = y; y->Mark(x->key);
}
inline void Cut(node *x) {
Access(x); Splay(x);
x->ch[0]->Mark(-x->key);
x->ch[0]->fa = null; x->ch[0] = null;
}
inline void Link(int x, int y) {
Link(T + x, T + y);
}
inline void Cut(int x) {
Cut(T + x);
}
inline int Val(int x) {
Splay(T + x); return T[x].key;
}
}
namespace SAM {
int to
[27];
int mx
, par
;
int last, root, Tcnt;
void Init(void) { last = root = Tcnt = 1; }
inline void Link(int x, int y) {
par[x] = y; LCT::Link(x, y);
}
inline int Extend(int c) {
int p = last, np = ++Tcnt;
mx[np] = mx[p] + 1; LCT::T[np].key = 1;
for (; p && !to[p][c]; p = par[p]) to[p][c] = np;
if (p) {
int q = to[p][c];
if (mx[q] != mx[p] + 1) {
int nq = ++Tcnt;
mx[nq] = mx[p] + 1;
memcpy(to[nq], to[q], sizeof to[q]);
Link(nq, par[q]); LCT::Cut(q);
Link(q, nq); Link(np, nq);
for (; to[p][c] == q; p = par[p])
to[p][c] = nq;
} else {
Link(np, q);
}
} else {
Link(np, root);
}
return last = np;
}
inline int Count(char *begin, char *end) {
int u = root;
for (char *c = begin; c != end; c++) {
int x = *c - 'A';
if (to[u][x]) u = to[u][x];
else return 0;
}
return LCT::Val(u);
}
}

int q, n, ans, mask;
char in
, opt
, s
;

inline void Decode(int mask) {
for (int i = 0; i < n; i++) {
mask = (mask * 131 + i) % n;
swap(s[mask], s[i]);
}
}

int main(void) {
freopen("1.in", "r", stdin);
read(q); read(in); n = strlen(in);
SAM::Init(); LCT::Init(666666 << 1);
for (int i = 0; i < n; i++)
SAM::Extend(in[i] - 'A');
while (q--) {
read(opt); read(s);
n = strlen(s); Decode(mask);
if (*opt == 'Q') {
printf("%d\n", ans = SAM::Count(s, s + n));
mask ^= ans;
} else {
for (int i = 0; i < n; i++)
SAM::Extend(s[i] - 'A');
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: