解析
所谓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_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endifm=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
*/