解析
所谓SAM套LCT,真的就只是SAM套LCT。。。
考试写起来应该有亿点点恶心
每次在SAM节点修改的时候在LCT对应位置修改即可。
注意! 克隆节点之前需要先splay一下把所有标记接收。
没了。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
const int N=3e6+100;
const int M=1e6+100;
const int mod=1e9;
int clo;
struct SAM;
struct LCT{
int tr[N][2],f[N],val[N],rev[N],add[N];
#define ls(o) tr[o][0]
#define rs(o) tr[o][1]
inline bool isroot(int x){
return ls(f[x])!=x&&rs(f[x])!=x;
}
inline bool which(int x){
return tr[f[x]][1]==x;
}
inline void Rev(int x){
if(x){
rev[x]^=1;swap(ls(x),rs(x));
}
return;
}
inline void Add(int x,int w){
if(x){
val[x]+=w;add[x]+=w;
}
return;
}
inline void pushdown(int x){
if(rev[x]){
rev[x]=0;
Rev(ls(x));Rev(rs(x));
}
if(add[x]){
int w=add[x];add[x]=0;
Add(ls(x),w);Add(rs(x),w);
}
return;
}
inline void rotate(int x){
int fa=f[x],gfa=f[fa];
int d=which(x),son=tr[x][d^1];
pushdown(gfa);pushdown(fa);pushdown(x);
f[x]=gfa;if(!isroot(fa)) tr[gfa][which(fa)]=x;
f[fa]=x;tr[x][d^1]=fa;
if(son){f[son]=fa;}tr[fa][d]=son;
}
int zhan[N];
inline void splay(int x){
int y=x,top=0;
zhan[++top]=y;
while(!isroot(y)) zhan[++top]=y=f[y];
while(top) pushdown(zhan[top--]);
for(int fa;fa=f[x],!isroot(x);rotate(x)){
if(!isroot(fa)) which(fa)==which(x)?rotate(fa):rotate(x);
}
return;
}
inline void access(int x){
for(int y(0);x;y=x,x=f[x]){
splay(x);
tr[x][1]=y;
if(y) f[y]=x;
}
return;
}
inline void makeroot(int x){
access(x);splay(x);Rev(x);
return;
}
inline int findroot(int x){
access(x);splay(x);
while(pushdown(x),tr[x][0]) x=tr[x][0];
return x;
}
inline void split(int x,int y){
makeroot(x);access(y);splay(y);
return;
}
inline void link(int x,int y){
//printf("link: %d - %d\n",x,y);
makeroot(x);makeroot(y);
if(findroot(x)==findroot(y)){
assert(0);
printf("!!\n");
return;
}
f[x]=y;
}
inline void cut(int x,int y){
//printf("cut: %d - %d\n",x,y);
split(x,y);
if(tr[y][0]!=x||tr[x][1]){
assert(0);
printf("??\n");
return;
}
tr[y][0]=0;f[x]=0;
return;
}
void newnode(int x,int f,int c=1){
link(x,f);
split(1,x);
Add(x,c);
return;
}
void print(int x){
if(!x) return;
printf("x=%d fa=%d ls=%d rs=%d val=%d rev=%d add=%d\n",
x,f[x],ls(x),rs(x),val[x],rev[x],add[x]);
print(ls(x));print(rs(x));
}
void Debug(){
printf("---debug:\n");
for(int i=1;i<=clo;i++){
if(isroot(i)) print(i);
}
putchar('\n');
}
}lct;
struct SAM{
int len[N],fa[N],tr[N][2],tot,lst;
SAM(){tot=lst=1;}
void ins(int c){
c-='A';
int cur=++tot,p=lst;lst=tot;
len[cur]=len[p]+1;
//printf("\n---ins: %d\n",c);
for(;p&&!tr[p][c];p=fa[p]) tr[p][c]=cur;
if(!tr[p][c]) fa[cur]=1;
else{
int q=tr[p][c];
if(len[q]==len[p]+1) fa[cur]=q;
else{
int nq=++tot;
len[nq]=len[p]+1;fa[nq]=fa[q];
for(int i=0;i<2;i++) tr[nq][i]=tr[q][i];
lct.splay(q);
lct.val[nq]=lct.val[q];
lct.cut(q,fa[q]);lct.link(nq,fa[q]);lct.link(q,nq);
fa[q]=fa[cur]=nq;
for(;p&&tr[p][c]==q;p=fa[p]) tr[p][c]=nq;
//printf(" clone(%d) = %d len=%d\n",q,nq,len[nq]);
}
}
clo=tot;
lct.newnode(cur,fa[cur]);
//lct.Debug();
return;
}
int work(char *s,int n){
int now=1;
for(int i=1;i<=n;i++){
int c=s[i]-'A';
//printf("now=%d c=%d tr=%d\n",now,c,tr[now][c]);
if(!tr[now][c]){
//printf("!");
return 0;
}
now=tr[now][c];
}
//printf("now=%d\n",now);
lct.splay(now);
return lct.val[now];
}
}sam;
int n,m;
char s[N],op[12],s0[N];
void get(int msk){
for(int i=0;i<n;i++) s0[i]=s[i+1];
for(int i=0;i<n;i++){
msk=(msk*131+i)%n;
swap(s0[i],s0[msk]);
//printf("i=%d msk=%d\n",i,msk);
}
for(int i=1;i<=n;i++) s[i]=s0[i-1];
return;
}
int msk;
signed main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
m=read();
scanf(" %s",s+1);n=strlen(s+1);
for(int i=1;i<=n;i++){
sam.ins(s[i]);
}
for(int i=1;i<=m;i++){
//debug("%d\n",i);
scanf(" %s %s",op+1,s+1);
n=strlen(s+1);
get(msk);
//printf("%s\n",s+1);
if(op[1]=='A'){
for(int j=1;j<=n;j++) sam.ins(s[j]);
}
else{
int res=sam.work(s,n);
printf("%d\n",res);
msk^=res;
}
}
return 0;
}
/*
8
AAAAAAA
Q A
Q AA
Q AAA
A BAB
Q A
Q AABB
Q AB
Q AABAB
*/