P5212 SubString
阿新 • • 發佈:2020-07-31
強制線上求不同字串。
由於sam中有新增邊,和刪除邊的操作,所以我們考慮使用lct來維護sam。
#include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<climits> #include<stack> #include<vector> #include<queue> #include<set> #include<bitset> #include<map> //#include<regex> #include<cstdio> #include <iomanip> #pragma GCC optimize(2) #define up(i,a,b) for(int i=a;i<b;i++) #define dw(i,a,b) for(int i=a;i>b;i--) #define upd(i,a,b) for(int i=a;i<=b;i++) #define dwd(i,a,b) for(int i=a;i>=b;i--) //#define local typedef long long ll; typedef unsigned long long ull; const double esp = 1e-6; const double pi = acos(-1.0); const int INF = 0x3f3f3f3f; const int inf = 1e9; using namespace std; ll read() { char ch = getchar(); ll x = 0, f = 1; while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } typedef pair<int, int> pir; #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lrt root<<1 #define rrt root<<1|1 const int N = 5e6 + 10; struct node { int ch[2], fa, lazy, val, tag; }tree[N << 1]; int mask = 0; string s, chars; int Q; void decodewithmask(int ms) { cin >> s; int len = s.size(); chars = s; up(i, 0, len) { ms = (ms * 131 + i) % len; char t = chars[i]; chars[i] = chars[ms]; chars[ms] = t; } } int ident(int rt, int fa) { return tree[fa].ch[1] == rt; } void connect(int rt, int fa, int son) { tree[rt].fa = fa; tree[fa].ch[son] = rt; } bool isroot(int rt) { int f = tree[rt].fa; return tree[f].ch[1] != rt && tree[f].ch[0] != rt; } void rev(int x) { swap(tree[x].ch[0], tree[x].ch[1]); tree[x].lazy ^= 1; } void pushdown(int rt) { if (tree[rt].lazy) { if (tree[rt].ch[0])rev(tree[rt].ch[0]); if (tree[rt].ch[1])rev(tree[rt].ch[1]); tree[rt].lazy = 0; } if (tree[rt].tag) { int ls = tree[rt].ch[0]; int rs = tree[rt].ch[1]; tree[ls].val += tree[rt].tag; tree[rs].val += tree[rt].tag; tree[ls].tag += tree[rt].tag; tree[rs].tag += tree[rt].tag; tree[rt].tag = 0; } } void pushall(int rt) { if (!isroot(rt))pushall(tree[rt].fa); pushdown(rt); } void rotate(int rt) { int f = tree[rt].fa; int ff = tree[f].fa; int k = ident(rt, f); connect(tree[rt].ch[k ^ 1], f, k); tree[rt].fa = ff; if (!isroot(f))tree[ff].ch[ident(f, ff)] = rt; connect(f, rt, k ^ 1); } void splay(int x) { pushall(x); while (!isroot(x)) { int f = tree[x].fa; int ff = tree[f].fa; if (!isroot(f)) ident(f, ff) ^ ident(x, f) ? rotate(x) : rotate(f); rotate(x); } } void access(int x) { for (int y = 0; x; x = tree[x].fa) { splay(x); tree[x].ch[1] = y; y = x; } } void makeroot(int x) { access(x); splay(x); rev(x); } void link(int x, int y) { tree[y].fa = x; } void split(int x, int y) { makeroot(x); access(y); splay(y); } void cut(int x, int y) { split(x, y); tree[x].fa = tree[y].ch[0] = 0; } struct sam { int trans[N << 1][2]; vector<int>par; int len[N << 1]; int tot, last; void init(int l) { par.resize(l + 1, 0); tot = last = 1; } void insert(int c) { int pre = last; int now = last = ++tot; len[now] = len[pre] + 1; for (; pre && !trans[pre][c]; pre = par[pre]) { trans[pre][c] = now; } if (!pre) { par[now] = 1; link(1, now); split(1, now); tree[now].val++; tree[now].tag++; } else { int ano = trans[pre][c]; if (len[ano] == len[pre] + 1) { par[now] = ano; link(ano, now); split(1, now); tree[now].val++; tree[now].tag++; } else { int nnow = ++tot; memcpy(trans[nnow], trans[ano], sizeof(trans[ano])); len[nnow] = len[pre] + 1; par[nnow] = par[ano]; cut(par[ano], ano); link(par[ano], nnow); link(nnow, now); link(nnow, ano); par[now] = par[ano] = nnow; tree[nnow].val = tree[ano].val; for (; pre&&trans[pre][c] == ano; pre = par[pre]) { trans[pre][c] = nnow; } split(1, now); tree[now].val++; tree[now].tag++; } } } }S; int main() { Q = read(); //std::ios::sync_with_stdio(false); S.init(1e7); cin >> s; int len = s.size(); up(i, 0, len)S.insert(s[i] - 'A'); char op[10]; while (Q--) { scanf("%s", op); if (op[0] == 'A') { decodewithmask(mask); int len = chars.size(); up(i, 0, len) S.insert(chars[i] - 'A'); } else { decodewithmask(mask); int len = chars.size(); int st = 1; up(i, 0, len) { st = S.trans[st][chars[i] - 'A']; } if (!st) { printf("0\n"); } else { splay(st); printf("%d\n", tree[st].val); mask ^= tree[st].val; } } } return 0; }