分析:
翻了一下这道题的提交记录,发现yhzq和Mario_sz两个月前就做过了(希望现在填坑还不算晚)
第一次看这道题,感觉就是一道SAM
支持动态添加?SAM可以啊
匹配?SAM也可以啊
然而上网,得到都是
LCT+SAM
L
C
T
+
S
A
M
,直接把我吓傻了
朴素的后缀自动机,每个节点维护一个
size
s
i
z
e
,添加一个字符时将它
parent
p
a
r
e
n
t
的
size
s
i
z
e
都加一
询问时沿着后缀自动机走,输出最后一个节点的
size
s
i
z
e
即可
但暴力维护会TLE,于是只能上LCT了
注意不仅要
link
l
i
n
k
新加进来的节点,在后缀自动机构建时
parent
p
a
r
e
n
t
改变后也要及时
link
l
i
n
k
和
cut
c
u
t
但是这个LCT没有
makeroot
m
a
k
e
r
o
o
t
操作
因为
parent
p
a
r
e
n
t
树是有向的,根不能随便改
tip
不知道为什么老是RE
后来发现是cut出了点问题
因为C++中连等式是从右到左计算的,所以右边的写法才能保证正确
pre[ch[x][0]]=ch[x][0]=0; ---> pre[ch[x][0]]=0; ch[x][0]=0;
T了一段时间
把函数放到struct里面就A了
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1200005;
int mask;
char s[3000005];
void gets(int mask)
{
scanf("%s",s);
int len=strlen(s);
for (int i=0;i<len;i++) {
mask=(mask*131+i)%len;
swap(s[i],s[mask]);
}
}
struct lct{
int ch[N][2],size[N],pre[N],tag[N];
int q[N],top;
int isroot(int bh) {
return ch[pre[bh]][0]!=bh&&ch[pre[bh]][1]!=bh;
}
int get(int bh) {
return (ch[pre[bh]][0]==bh? 0:1);
}
void push(int bh) {
if (tag[bh]==0) return;
if (ch[bh][0]) size[ch[bh][0]]+=tag[bh],tag[ch[bh][0]]+=tag[bh];
if (ch[bh][1]) size[ch[bh][1]]+=tag[bh],tag[ch[bh][1]]+=tag[bh];
tag[bh]=0;
}
void rotate(int bh) {
int fa=pre[bh];
int grand=pre[fa];
int wh=get(bh);
if (!isroot(fa)) ch[grand][ch[grand][0]==fa? 0:1]=bh;
ch[fa][wh]=ch[bh][wh^1];
pre[ch[fa][wh]]=fa;
ch[bh][wh^1]=fa;
pre[fa]=bh;
pre[bh]=grand;
}
void splay(int bh) {
int top=0;
q[++top]=bh;
for (int i=bh;!isroot(i);i=pre[i]) q[++top]=pre[i];
while (top) push(q[top--]);
for (int fa;!isroot(bh);rotate(bh))
if (!isroot(fa=pre[bh]))
rotate(get(bh)==get(fa) ? fa:bh);
}
void expose(int bh) {
int t=0;
while (bh) {
splay(bh);
ch[bh][1]=t;
t=bh;
bh=pre[bh];
}
}
void link(int x,int y) {
expose(y);
splay(y);
pre[x]=y;
size[y]+=size[x];
tag[y]+=size[x];
}
void cut(int x){
expose(x);
splay(x);
size[ch[x][0]]-=size[x];
tag[ch[x][0]]-=size[x];
pre[ch[x][0]]=0;ch[x][0]=0;
}
}t;
struct sam{
int dis[N],fa[N],ch[N][26];
int sz,last;
void insert(int x) {
int pre=last,now=++sz;
last=now;
dis[now]=dis[pre]+1;
for (;pre&&!ch[pre][x];pre=fa[pre]) ch[pre][x]=now;
if (!pre) fa[now]=1;
else {
int q=ch[pre][x];
if (dis[q]==dis[pre]+1)
fa[now]=q;
else {
int nows=++sz;
memcpy(ch[nows],ch[q],sizeof(ch[q]));
dis[nows]=dis[pre]+1;
fa[nows]=fa[q];
t.link(nows,fa[nows]); t.cut(q);
fa[q]=fa[now]=nows;
t.link(q,nows);
for (;pre&&ch[pre][x]==q;pre=fa[pre]) ch[pre][x]=nows;
}
}
t.size[now]=1;
t.link(now,fa[now]);
}
void build(){
last=++sz;
scanf("%s",s);
int l=strlen(s);
for(int i=0;i<l;i++)
insert(s[i]-'A');
}
void add(){
gets(mask);
int l=strlen(s);
for(int i=0;i<l;i++)
insert(s[i]-'A');
}
int solve(){
gets(mask);
int p=1,l=strlen(s);
for(int i=0;i<l;i++)
if(!(p=ch[p][s[i]-'A']))return 0;
t.splay(p);
return t.size[p];
}
}sam;
int main()
{
int Q;
scanf("%d",&Q);
sam.build();
while(Q--)
{
scanf("%s",s);
if(s[0]=='A') sam.add();
else
{
int ans=sam.solve();
printf("%d\n",ans);
mask^=ans;
}
}
return 0;
}