后缀自动机+LCT
终于做了这道题
思路比较明显,每次的答案就是走到的最终节点的Right集合大小,如果走不到就是0。但是问题在于每次添加字符后parent树的形态变了,那么Right集合也要变化,这个我们用LCT维护,由于是有根树,比较好维护。
#include<bits/stdc++.h> using namespace std; const int N = 1.2e6 + 5; struct node { int val, par; int ch[26]; } t[N]; int n, m, mask, top; int st[N]; char opt[20], s[N << 1]; void decode(char *s, int mask) { int len = strlen(s); for(int i = 0; i < len; ++i) { mask = (mask * 131 + i) % len; swap(s[i], s[mask]); } } namespace LCT { int fa[N], ch[N][2], tag[N], sum[N]; void paint(int x, int d) { if(!x) return; tag[x] += d; sum[x] += d; } bool wh(int x) { return x == ch[fa[x]][1]; } bool isr(int x) { return !fa[x] || (ch[fa[x]][0] != x && ch[fa[x]][1] != x); } void pushdown(int x) { if(tag[x]) { paint(ch[x][0], tag[x]); paint(ch[x][1], tag[x]); tag[x] = 0; } } void up(int x) { top = 0; while(!isr(x)) { st[++top] = x; x = fa[x]; } st[++top] = x; for(int i = top; i; --i) pushdown(st[i]); } void rotate(int x) { int f = fa[x], t = wh(x); fa[x] = fa[f]; if(!isr(f)) ch[fa[f]][wh(f)] = x; fa[f] = x; ch[f][t] = ch[x][t ^ 1]; fa[ch[x][t ^ 1]] = f; ch[x][t ^ 1] = f; } void splay(int x) { up(x); while(!isr(x)) { if(!isr(fa[x])) rotate(wh(x) == wh(fa[x]) ? fa[x] : x); rotate(x); } } void access(int x) { for(int f = 0; x; f = x, x = fa[x]) { splay(x); ch[x][1] = f; } } void link(int x, int y) { fa[x] = y; access(y); splay(y); paint(y, sum[x]); } void cut(int x) { access(x); splay(x); paint(ch[x][0], -sum[x]); fa[ch[x][0]] = 0; ch[x][0] = 0; } } using namespace LCT; namespace SAM { int last = 1, sz = 1, root = 1; int nw(int x) { t[++sz].val = x; return sz; } void extend(int c) { int p = last, np = nw(t[p].val + 1); sum[np] = 1; while(p && !t[p].ch[c]) t[p].ch[c] = np, p = t[p].par; if(!p) t[np].par = root, link(np, root); else { int q = t[p].ch[c]; if(t[q].val == t[p].val + 1) t[np].par = q, link(np, q); else { int nq = nw(t[p].val + 1); memcpy(t[nq].ch, t[q].ch, sizeof(t[q].ch)); link(nq, t[q].par); cut(q); link(q, nq); link(np, nq); t[nq].par = t[q].par; t[q].par = t[np].par = nq; while(p && t[p].ch[c] == q) t[p].ch[c] = nq, p = t[p].par; } } splay(np); last = np; } void add(char *s) { int len = strlen(s); for(int i = 0; i < len; ++i) extend(s[i] - 'A'); } void query(char *s) { int len = strlen(s), u = root; for(int i = 0; i < len; ++i) { if(!t[u].ch[s[i] - 'A']) { puts("0"); return; } u = t[u].ch[s[i] - 'A']; } up(u); printf("%d\n", sum[u]); mask ^= sum[u]; } } using namespace SAM; int main() { scanf("%d%s", &m, s); n = strlen(s); for(int i = 0; i < n; ++i) extend(s[i] - 'A'); while(m--) { scanf("%s%s", opt, s); decode(s, mask); if(opt[0] == 'A') add(s); if(opt[0] == 'Q') query(s); } return 0; }