传送门biu~
查询一个串出现了几次,即询问SAM上表示这个串的的Right数组有几个。当我们向SAM上添加一个节点时,这个节点在parent树上到根的路径上的所有节点Right数组数量都会+1。可以用LCT维护。
本来说快省选了在省选完挂之前写一道听起来很厉害的SAM+LCT,退役了也没什么遗憾了。没想到其实就是在维护SAM的时候顺便维护一个LCT,而且还1A了。生活失去了色彩,退役了退役了。。。
#include<bits/stdc++.h>
using namespace std;
struct splay{
splay *fa,*ch[2];
int mark,val;
splay();
inline void pushdown();
inline void add(int);
inline int dir(){
if(fa->ch[0]==this) return 0;
if(fa->ch[1]==this) return 1;
return -1;
}
}*null=new splay;
splay :: splay(){
fa=ch[0]=ch[1]=null;
mark=val=0;
}
inline void splay :: add(int v){
if(this==null) return;
val+=v; mark+=v;
}
inline void splay :: pushdown(){
if(!mark) return;
ch[0]->add(mark);
ch[1]->add(mark);
mark=0;
}
void To_pushdown(splay *o){
if(~o->dir()) To_pushdown(o->fa);
o->pushdown();
}
inline void Rotate(splay *o,int d){
splay *k=o->ch[d^1];
o->ch[d^1]=k->ch[d]; k->ch[d]->fa=o;
k->ch[d]=o;
if(~o->dir()) o->fa->ch[o->dir()]=k;
k->fa=o->fa; o->fa=k;
}
inline void Splay(splay *o){
To_pushdown(o);
while(~o->dir()){
if(o->dir()==o->fa->dir()) Rotate(o->fa->fa,o->dir()^1);
Rotate(o->fa,o->dir()^1);
}
}
inline void Access(splay *o){
splay *p=null;
while(o!=null){
Splay(o);
o->ch[1]=p;
p=o;
o=o->fa;
}
}
inline void Cut(splay *o){
Access(o); Splay(o);
o->ch[0]=o->ch[0]->fa=null;
}
inline void Link(splay *x,splay *y){
Cut(x); x->fa=y;
}
struct Node{
Node *fa,*ch[26];
int val;
splay *tree;
Node(int _=0){
fa=0x0; val=_;
memset(ch,0x0,sizeof ch);
tree=new splay;
}
}*root=new Node,*last=root;
inline void Insert(int x){
Node *p=last,*np=new Node(p->val+1);last=np;
while(p && !p->ch[x]) p->ch[x]=np,p=p->fa;
if(!p) np->fa=root,Link(np->tree,root->tree);
else{
Node *q=p->ch[x];
if(q->val==p->val+1) np->fa=q,Link(np->tree,q->tree);
else{
Node *nq=new Node(p->val+1);
nq->fa=q->fa; Link(nq->tree,q->fa->tree);
memcpy(nq->ch,q->ch,sizeof nq->ch);
q->fa=nq; Link(q->tree,nq->tree);
np->fa=nq; Link(np->tree,nq->tree);
To_pushdown(q->tree);
nq->tree->val=q->tree->val;
while(p && p->ch[x]==q) p->ch[x]=nq,p=p->fa;
}
}
Access(np->tree);
Splay(np->tree);
np->tree->add(1);
}
char s[600005];
inline void s_Insert(){
for(int i=0;s[i];++i) Insert(s[i]-'A');
}
inline int search(){
Node *o=root;
for(int i=0;s[i];++i){
if(!o->ch[s[i]-'A']) return 0;
o=o->ch[s[i]-'A'];
}
To_pushdown(o->tree);
return o->tree->val;
}
inline void Decode(int mask){
int n=strlen(s);
for(int i=0;i<n;++i){
mask=(mask*131+i)%n;
swap(s[i],s[mask]);
}
}
int main(){
int n;
scanf("%d%s",&n,s);
s_Insert();
int mask=0;
for(int i=1;i<=n;++i){
char opt[10];
scanf("%s%s",opt,s);
Decode(mask);
if(opt[0]=='A') s_Insert();
else{
int ans=search();
mask^=ans;
printf("%d\n",ans);
}
}
return 0;
}