Description
懶得寫背景了,給你一個字符串init,要求你支持兩個操作
(1):在當前字符串的後面插入一個字符串
(2):詢問字符串s在當前字符串中出現了幾次?(作爲連續子串)
你必須在線支持這些操作。
Input
第一行一個數Q表示操作個數
第二行一個字符串表示初始字符串init
接下來Q行,每行2個字符串Type,Str
Type是ADD的話表示在後面插入字符串。
Type是QUERY的話表示詢問某字符串在當前字符串中出現了幾次。
爲了體現在線操作,你需要維護一個變量mask,初始值爲0
讀入串Str之後,使用這個過程將之解碼成真正詢問的串TrueStr。
詢問的時候,對TrueStr詢問後輸出一行答案Result
然後mask = mask xor Result
插入的時候,將TrueStr插到當前字符串後面即可。
HINT:ADD和QUERY操作的字符串都需要解壓
Output
Sample Input
A
QUERY B
ADD BBABBBBAAB
Sample Output
0
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 600005;
int sum[MAXN << 1], fa[MAXN << 1], lc[MAXN << 1], rc[MAXN << 1], cnt[MAXN << 1];
int ch[MAXN << 1][26], pre[MAXN << 1], dis[MAXN << 1], num[MAXN << 1];
int n, i, j, k, l, m, t = 1, p = 1, q, tag[MAXN << 1], len, tot;
char s[MAXN], c[10];
inline bool isroot(int x)
{
return (lc[fa[x]] == x || rc[fa[x]] == x);
}
inline void rev(int x)
{
swap(lc[x], rc[x]);
cnt[x] ^= 1;
}
inline void putdown(int x)
{
if (cnt[x])
{
cnt[x] = 0;
if (lc[x]) rev(lc[x]);
if (rc[x]) rev(rc[x]);
}
if (num[x])
{
if (lc[x]) num[lc[x]] += num[x], sum[lc[x]] += num[x];
if (rc[x]) num[rc[x]] += num[x], sum[rc[x]] += num[x];
num[x] = 0;
}
}
inline void turn(int x)
{
int y = fa[x], z = fa[y], b = 0;
if (lc[y] == x) b = rc[x];
else b = lc[x];
if (b) fa[b] = y;
fa[x] = z; fa[y] = x;
if (z)
if (lc[z] == y) lc[z] = x;
else if (rc[z] == y) rc[z] = x;
if (lc[y] == x) rc[x] = y, lc[y] = b;
else lc[x] = y, rc[y] = b;
}
inline void splay(int x)
{
int i;
for(i = x; isroot(i); i = fa[i])
tag[++len] = i;
tag[++len] = i;
while (len) putdown(tag[len --]);
while (isroot(x))
{
if (isroot(fa[x]))
if ((lc[fa[x]] == x) == (lc[fa[fa[x]]] == fa[x])) turn(fa[x]);
else turn(x);
turn(x);
}
}
inline void access(int x)
{
int sb = 0;
while (x)
{
splay(x);
rc[x] = sb;
sb = x;
x = fa[x];
}
}
inline void makeroot(int x)
{
access(x);
splay(x);
rev(x);
}
inline void split(int x, int y, int w)
{
makeroot(x);
access(y);
splay(y);
num[y] += w;
sum[y] += w;
}
inline void Link(int x, int y)
{
makeroot(x);
fa[x] = y;
if (sum[x]) split(y, 1, sum[x]);
}
inline void Cut(int x, int y)
{
makeroot(x);
access(y);
splay(y);
lc[y] = fa[x] = 0;
if (sum[x]) split(y, 1, -sum[x]);
}
inline void add(int x)
{
int np = ++t;
sum[np] = 1;
dis[np] = dis[p] + 1;
for(; p && !ch[p][x]; p = pre[p])
ch[p][x] = np;
if (!p) pre[np] = 1, Link(np, 1);
else {
int q = ch[p][x];
if (dis[q] == dis[p] + 1) pre[np] = q, Link(np, q);
else {
int nq = ++t;
dis[nq] = 1 + dis[p];
for(int i = 0; i < 26; i ++)
ch[nq][i] = ch[q][i];
pre[nq] = pre[q];
Link(nq, pre[nq]);
Cut(q, pre[q]);
pre[np] = pre[q] = nq;
Link(np, nq);
Link(q, nq);
for(; p && ch[p][x] == q; p = pre[p])
ch[p][x] = nq;
}
}
p = np;
}
int main()
{
cin >> q;
scanf("%s", s + 1);
n = strlen(s + 1);
for(i = 1; i <= n; i ++)
add(s[i] - 'A');
while (q --)
{
scanf("%s", c);
scanf("%s", s);
n = strlen(s);
int tot1 = tot;
for(i = 0; i < n; i ++)
{
tot = (tot * 131 + i) % n;
swap(s[i], s[tot]);
}
tot = tot1;
if (c[0] == 'A')
{
for(i = 0; i < n; i ++)
add(s[i] - 'A');
}
else
{
int pyz = 0, now = 1, fp = 0;
for(i = 0; i < n; i ++)
{
int x = s[i] - 'A';
if (ch[now][x]) now = ch[now][x], pyz ++;
else {
for(; now && !ch[now][x]; now = pre[now]);
if (!now) now = 1, pyz = 0;
else pyz = dis[now] + 1, now = ch[now][x];
}
if (pyz == n) {splay(now); printf("%d\n", sum[now]); tot ^= sum[now]; fp = 1; break;}
}
if (!fp) {printf("0\n"); tot ^= 0;}
}
}
}