[后缀自动机][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; }
相关文章推荐
- bzoj 2555: SubString 后缀自动机+LCT
- BZOJ2555:SubString 后缀自动机 LCT
- bzoj 2555: SubString 后缀自动机+lct
- [BZOJ2555]SubString(后缀自动机+LCT)
- BZOJ2555 SubString 后缀自动机+LCT
- bzoj 2555: SubString 后缀自动机+lct
- 【bzoj2555】SubString 后缀自动机+LCT
- [后缀自动机 LCT] BZOJ 2555 SubString
- bzoj 2555 SubString 后缀自动机 LCT
- BZOJ 2555: SubString [后缀自动机 LCT]
- BZOJ 2555: SubString 后缀自动机+LCT
- BZOJ2555 SubString 【后缀自动机 + LCT】
- 【bzoj2555】SubString LCT+后缀自动机
- 后缀自动机 + LCT 【bzoj2555】SubString
- [BZOJ2555]-SubString-后缀自动机+LCT维护parent树
- bzoj 2555: SubString 后缀自动机+LCT
- [BZOJ2555]SubString(后缀自动机+lct)
- 字符串(LCT,后缀自动机):BZOJ 2555 SubString
- [BZOJ]2555 Substring 后缀自动机&LCT
- 【后缀自动机+LCT】BZOJ2555[SubString]题解