BZOJ2555: SubString
Description
懒得写背景了,给你一个字符串init,要求你支持两个操作
(1):在当前字符串的后面插入一个字符串
(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
你必须在线支持这些操作。
Input
第一行一个数Q表示操作个数
第二行一个字符串表示初始字符串init
接下来Q行,每行2个字符串Type,Str
Type是ADD的话表示在后面插入字符串。
Type是QUERY的话表示询问某字符串在当前字符串中出现了几次。
为了体现在线操作,你需要维护一个变量mask,初始值为0
读入串Str之后,使用这个过程将之解码成真正询问的串TrueStr。
询问的时候,对TrueStr询问后输出一行答案Result
然后mask = mask xor Result
插入的时候,将TrueStr插到当前字符串后面即可。
HINT:ADD和QUERY操作的字符串都需要解压
Output
Sample Input
2
A
QUERY B
ADD BBABBBBAAB
A
QUERY B
ADD BBABBBBAAB
Sample Output
0
HINT
40 % 的数据字符串最终长度 <= 20000,询问次数<= 1000,询问总长度<= 10000
100 % 的数据字符串最终长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000
新加数据一组--2015.05.20
考虑修改的是模式串,可以用SAM,考虑动态修改,可以用LCT来维护fa指针与end-set集大小。
然后就是写代码的问题了。
get函数写错了调了半天233
注意:BZOJ不能写连等号(pre[ch[x][0]]=ch[x][0]=0;),否则会又R又T得飞起。
#include<cstdio> #include<cctype> #include<queue> #include<cstring> #include<algorithm> #define lc ch[x][0] #define rc ch[x][1] #define rep(s,t) for(int i=s;i<=t;i++) #define ren for(int i=first[x];i!=-1;i=next[i]) using namespace std; const int maxn=1200010; const int maxm=3000010; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } char s[maxm]; void get(int mask) { scanf("%s",s);int n=strlen(s); rep(0,n-1) { mask=(mask*131+i)%n; swap(s[i],s[mask]); } } int mask; struct LCT { int fa[maxn],pre[maxn],ch[maxn][2],addv[maxn],w[maxn]; void Add(int x,int y) { if(x) addv[x]+=y,w[x]+=y; } void pushdown(int x) { if(addv[x]) Add(lc,addv[x]),Add(rc,addv[x]); addv[x]=0; } void rotate(int x) { int y=pre[x],z=pre[y],d=ch[y][0]==x; ch[y][d^1]=ch[x][d];pre[ch[x][d]]=y; ch[z][ch[z][1]==y]=x;pre[x]=z; ch[x][d]=y;pre[y]=x; } int top,S[maxn]; void splay(int x) { for(int i=x;i;i=pre[i]) S[++top]=i; if(top!=1) fa[x]=fa[S[top]]; while(top) pushdown(S[top--]); while(pre[x]) rotate(x); } void access(int x) { for(int y=0;x;x=fa[x]) { splay(x);fa[ch[x][1]]=x;pre[ch[x][1]]=0; ch[x][1]=y;pre[y]=x;y=x; } } void link(int x,int f) {fa[x]=f;access(f);splay(f);Add(f,w[x]);} void cut(int x) {access(x);splay(x);Add(ch[x][0],-w[x]);pre[ch[x][0]]=0;ch[x][0]=0;} }lct; struct SAM { int l[maxn],fa[maxn],to[maxn][26],cnt,last; SAM() {cnt=last=1;} void extend(int c) { int p,q,np,nq; p=last;last=++cnt;np=cnt;lct.w[np]=1;l[np]=l[p]+1; for(;!to[p][c];p=fa[p]) to[p][c]=np; if(!p) fa[np]=1,lct.link(np,1); else { q=to[p][c]; if(l[p]+1==l[q]) fa[np]=q,lct.link(np,q); else { nq=++cnt;l[nq]=l[p]+1; memcpy(to[nq],to[q],sizeof(to[q])); fa[nq]=fa[q];lct.link(nq,fa[q]); fa[q]=nq;fa[np]=nq;lct.cut(q);lct.link(q,nq);lct.link(np,nq); for(;to[p][c]==q;p=fa[p]) to[p][c]=nq; } } } int query() { int p=1; for(int i=0;s[i];i++) if(!(p=to[p][s[i]-'A'])) return 0; lct.splay(p);return lct.w[p]; } void add() { for(int i=0;s[i];i++) extend(s[i]-'A'); } }sol; char cmd[12]; int main() { int n=read();scanf("%s",s); sol.add(); while(n--) { scanf("%s",cmd);get(mask); if(cmd[0]=='Q') { int ans=sol.query(); printf("%d\n",ans); mask^=ans; } else sol.add(); } return 0; }