【bzoj2555】SubString
*题目描述:
懒得写背景了,给你一个字符串init,要求你支持两个操作
(1):在当前字符串的后面插入一个字符串
(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
你必须在线支持这些操作。
*输入:
第一行一个数Q表示操作个数
第二行一个字符串表示初始字符串init
接下来Q行,每行2个字符串Type,Str
Type是ADD的话表示在后面插入字符串。
Type是QUERY的话表示询问某字符串在当前字符串中出现了几次。
为了体现在线操作,你需要维护一个变量mask,初始值为0
读入串Str之后,使用这个过程将之解码成真正询问的串TrueStr。
询问的时候,对TrueStr询问后输出一行答案Result
然后mask = mask xor Result
插入的时候,将TrueStr插到当前字符串后面即可。
HINT:ADD和QUERY操作的字符串都需要解压
*输出:
*样例输入:
2
A
QUERY B
ADD BBABBBBAAB
*样例输出:
0
*提示:
40 % 的数据字符串最终长度 <= 20000,询问次数<= 1000,询问总长度<= 10000
100 % 的数据字符串最终长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000
新加数据一组–2015.05.20
*来源:
Ctsc模拟赛By 洁妹
*题解:
用link-cut tree维护SAM。lct维护的是fail树的子树大小,因为是动态插入字符串,有可能一些节点需要换父亲,所以需要lct。
*代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif
#ifdef CT
#define debug(...) printf(__VA_ARGS__)
#define setfile()
#else
#define debug(...)
#define filename ""
#define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout);
#endif
#define R register
#define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
#define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
#define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
#define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
char B[1 << 15], *S = B, *T = B;
inline int FastIn()
{
R char ch; R int cnt = 0; R bool minus = 0;
while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
ch == '-' ? minus = 1 : cnt = ch - '0';
while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
return minus ? -cnt : cnt;
}
#define maxn 6000010
char str[maxn];
struct lct *null;
struct lct
{
lct *fa, *ch[2];
int sum, val;
inline bool type()
{
return fa -> ch[1] == this;
}
inline bool check()
{
return fa -> ch[type()] == this;
}
inline void update()
{
sum = val + ch[0] -> sum + ch[1] -> sum;
}
inline void modify(R int x)
{
val += x; sum += x;
}
inline void rotate()
{
R lct *f = fa;
R bool d = type();
(fa = f -> fa), f -> check() ? fa -> ch[f -> type()] = this : 0;
(f -> ch[d] = ch[!d]) != null ? ch[!d] -> fa = f : 0;
f -> fa = this;
ch[!d] = f;
f -> update();
}
inline void splay()
{
for ( ; check(); rotate())
if (fa -> check())
(type() != fa -> type() ? this : fa) -> rotate();
update();
}
inline lct *access()
{
R lct *i = this, *j = null;
for ( ; i != null; i = (j = i) -> fa)
{
i -> splay();
i -> modify(i -> ch[1] -> sum - j -> sum);
i -> ch[1] = j;
i -> update();
}
}
inline void link(R lct *f)
{
splay();
(fa = f) -> access();
f -> splay();
f -> modify(sum);
}
inline void cut()
{
access();
splay();
ch[0] = ch[0] -> fa = null;
update();
}
} mem[maxn];
struct sam *head;
struct sam
{
sam *fa, *next[2];
int max;
inline void modify(R sam *f)
{
if (fa) (mem + (this - head) + 1) -> cut();
(mem + (this - head) + 1) -> link(mem + ((fa = f) - head) + 1);
}
inline int query()
{
R lct *p = mem + (this - head + 1);
p -> access();
p -> splay();
return p -> val;
}
} sam_mem[maxn << 1], *tot = sam_mem, *cur = sam_mem;
inline sam *newnode(R int v)
{
mem[++tot - sam_mem + 1] = (lct) {null, null, null, v, v};
return tot;
}
inline void extend(R int w)
{
R sam *p = cur, *np = newnode(1);
(cur = np) -> max = p -> max + 1;
for( ; p && !p -> next[w]; p = p -> fa)
p -> next[w] = np;
if(!p) np -> modify(sam_mem);
else
{
R sam *q = p -> next[w];
if(q -> max == p -> max + 1)
np -> modify(q);
else
{
R sam *nq = newnode(0);
memcpy(nq -> next, q -> next, sizeof nq -> next);
nq -> max = p -> max + 1;
nq -> modify(q -> fa);
q -> modify(nq);
np -> modify(nq);
for( ; p && p -> next[w] == q; p = p -> fa)
p -> next[w] = nq;
}
}
}
inline void decodewithmask(R int mask)
{
scanf("%s", str);
R int len = strlen(str);
for (R int i = 0; i < len; ++i)
{
mask = (mask * 131 + i) % len;
R char tmp = str[i];
str[i] = str[mask];
str[mask] = tmp;
}
}
inline int query()
{
R sam *p = sam_mem;
R int l = strlen(str);
for (R int i = 0; i < l && p; ++i)
p = p -> next[str[i] - 'A'];
return p ? p -> query() : 0;
}
char opt[maxn];
int main()
{
// setfile();
null = mem; head = sam_mem;
null -> fa = null -> ch[0] = null -> ch[1] = null; null -> sum = null -> val = 0;
mem[1] = mem[0];
R int n, len, mask = 0;
scanf("%d", &n);
scanf("%s", str + 1);
len = strlen(str + 1);
for (R int i = 1; i <= len; ++i) extend(str[i] - 'A');
for (R int i = 1; i <= n; ++i)
{
scanf("%s", opt);
decodewithmask(mask);
if (opt[0] == 'Q')
{
R int ans = query();
printf("%d\n", ans );
mask ^= ans;
}
else
{
R int l = strlen(str);
for (R int i = 0; i < l; ++i)
extend(str[i] - 'A');
}
}
return 0;
}
/*
2
A
QUERY B
ADD BBABBBBAAB
*/