題目概述
給出初始字符串
解題報告
(之前做了後綴自動機和LCT就tm爲了這道題)強制在線插入詢問,後綴數組,KMP全都不行。數據範圍又賊大,我們想到後綴自動機。
後綴自動機求字符串
因爲有插入操作,所以需要動態維護parent樹,這就使我們想到了LCT維護子樹信息,接下來就是碼農時間了QAQ。
示例程序
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1200000,maxl=3000000,maxi=26;
int te,lstans;char s[maxl+5];bool vis[maxn+5];
int si,ro,p,son[maxn+5][maxi],fa[maxn+5],MAX[maxn+5];
inline char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
if (l==r) return EOF;return *l++;
}
inline int reads(char *s){
int len=0;char ch=readc();while (!isupper(ch)) ch=readc();
while (isupper(ch)) s[++len]=ch,ch=readc();s[len+1]=0;return len;
}
inline void Decode(char *s,int m){
for (int len=strlen(s),i=0;i<len;i++)
m=(m*131+i)%len,swap(s[i],s[m]);
}
#define is_ro(p) ((p)!=son[fa[p]][0]&&(p)!=son[fa[p]][1])
#define Son(p) ((p)==son[fa[p]][1])
namespace LCT{
int son[maxn+5][2],fa[maxn+5],si[maxn+5][2];bool flip[maxn+5];
inline void Pushup(int p) {si[p][1]=si[son[p][0]][1]+si[son[p][1]][1]+si[p][0]+vis[p];}
inline void Rotate(int t){
int p=fa[t],d=Son(t);son[p][d]=son[t][d^1];son[t][d^1]=p;
Pushup(p);Pushup(t);if (!is_ro(p)) son[fa[p]][Son(p)]=t;
if (son[p][d]) fa[son[p][d]]=p;fa[t]=fa[p];fa[p]=t;
}
inline void Addflip(int p) {swap(son[p][0],son[p][1]);flip[p]^=1;}
inline void Pushdown(int p) {if (flip[p]) flip[p]^=1,Addflip(son[p][0]),Addflip(son[p][1]);}
inline void Splay(int p){
static int top,stk[maxn+5];stk[top=1]=p;
for (int i=p;!is_ro(i);i=fa[i]) stk[++top]=fa[i];
while (top) Pushdown(stk[top--]);
for (int pre=fa[p];!is_ro(p);Rotate(p),pre=fa[p])
if (!is_ro(pre)) Rotate(Son(p)==Son(pre)?pre:p);
}
inline void Access(int p){
for (int lst=0;p;Pushup(p),lst=p,p=fa[p])
Splay(p),si[p][0]+=si[son[p][1]][1]-si[lst][1],son[p][1]=lst;
}
inline void Makero(int x) {Access(x);Splay(x);Addflip(x);}
inline void Link(int x,int y) {Makero(x);Makero(y);fa[x]=y;si[y][0]+=si[x][1];Pushup(y);}
inline void Cut(int x,int y) {Makero(x);Access(y);Splay(y);fa[x]=son[y][0]=0;Pushup(y);}
}
inline void Update(int x,bool f) {LCT::Makero(x);vis[x]=f;LCT::Pushup(x);}
#define newnode(m,f) (fa[++si]=0,Update(si,f),MAX[si]=m,memset(son[si],0,sizeof(son[si])),si)
inline void Extend(int c){
int np=newnode(MAX[p]+1,true);while (p&&!son[p][c]) son[p][c]=np,p=fa[p];
if (!p) fa[np]=ro,LCT::Link(np,ro); else{
int q=son[p][c];
if (MAX[p]+1==MAX[q]) fa[np]=q,LCT::Link(np,q); else{
int nq=newnode(MAX[p]+1,false);memcpy(son[nq],son[q],sizeof(son[q]));
LCT::Cut(q,fa[q]);fa[nq]=fa[q];LCT::Link(nq,fa[q]);
fa[np]=fa[q]=nq;LCT::Link(q,nq);LCT::Link(np,nq);
while (p&&son[p][c]==q) son[p][c]=nq,p=fa[p];
}
}
p=np;
}
inline int Sum(char *s){
int p=ro;for (int i=1;s[i];i++) p=son[p][s[i]-'A'];if (!p) return 0;
LCT::Makero(ro);LCT::Access(p);LCT::Splay(p);int ans=LCT::si[p][0]+vis[p];
return lstans^=ans,ans;
}
int main(){
freopen("program.in","r",stdin);
freopen("program.out","w",stdout);
scanf("%d",&te);reads(s);ro=newnode(0,false);p=ro;
for (int i=1;s[i];i++) Extend(s[i]-'A');
while (te--){
reads(s);
if (s[1]=='Q') reads(s),Decode(s+1,lstans),printf("%d\n",Sum(s));
else {reads(s);Decode(s+1,lstans);for (int i=1;s[i];i++) Extend(s[i]-'A');}
}
return 0;
}