BZOJ2555: SubString
题解: 建出SAM 用LCT维护Right集合即可
#include <bits/stdc++.h> const int MAXN=3e6+10; using namespace std; int key[MAXN],dis[MAXN],ch[MAXN][2],chl[MAXN][26],fa[MAXN]; int pre[MAXN],sum[MAXN],sumx[MAXN];//sum xu sumx all bool rt[MAXN]; int cnt,cur,root,mask; char s1[MAXN],s2[MAXN]; void up(int x){sumx[x]=sumx[ch[x][0]]+sumx[ch[x][1]]+sum[x]+key[x];} void Treavel(int x) { if(x) { Treavel(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d key=%2d,sum=%2d,sumx=%2d\n",x,ch[x][0],ch[x][1],pre[x],key[x],sum[x],sumx[x]); Treavel(ch[x][1]); } } void debug(int rp) { printf("root:%d\n",rp); Treavel(rp); } void read(int t) { scanf("%s",s2); int i,l = strlen(s2); for(i = 0 ; i < l ; i ++ ) t=(t*131+i)%l,swap(s2[i],s2[t]); } void newnode(int x,int vul){ key[x]=sumx[x]=vul;sum[x]=0;rt[x]=1;ch[x][0]=ch[x][1]=0;pre[x]=0; } void rotate(int x,int kind){ int y=pre[x]; ch[y][!kind]=ch[x][kind];pre[ch[x][kind]]=y; if(rt[y])rt[x]=1,rt[y]=0; else ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y];ch[x][kind]=y;pre[y]=x; up(y); } void splay(int x){ while(!rt[x]){ if(rt[pre[x]])rotate(x,ch[pre[x]][0]==x); else{ int y=pre[x];int kind=ch[pre[y]][0]==y; if(ch[y][kind]==x)rotate(x,!kind),rotate(x,kind); else rotate(y,kind),rotate(x,kind); } } up(x); } void access(int x){ int y=0; while(x){ splay(x); if(ch[x][1])pre[ch[x][1]]=x,rt[ch[x][1]]=1,sum[x]+=sumx[ch[x][1]]; if(y)rt[y]=0,sum[x]-=sumx[y]; ch[x][1]=y;up(x); y=x;x=pre[x]; } } void Link(int u,int v){ access(u);splay(u); access(v);splay(v); pre[u]=v;sum[v]+=sumx[u];up(v); } void destory(int u,int v){ access(u);splay(v); ch[v][1]=0;pre[u]=0;rt[u]=1;up(v); } int querty(int x){ access(x);splay(x); return sumx[x]-sumx[ch[x][0]]; } void built(int x,int id){ int last=cur;cur=++cnt;int p=last;dis[cur]=id;newnode(cur,1); for(;p&&!chl[p][x];p=fa[p])chl[p][x]=cur; if(!p)fa[cur]=root,Link(cur,root); else{ int q=chl[p][x]; if(dis[q]==dis[p]+1)fa[cur]=q,Link(cur,q); else{ int nt=++cnt;dis[nt]=dis[p]+1;newnode(cnt,0); memcpy(chl[nt],chl[q],sizeof(chl[q])); destory(q,fa[q]); fa[nt]=fa[q];Link(nt,fa[q]);fa[q]=fa[cur]=nt;Link(q,nt);Link(cur,nt); for(;chl[p][x]==q;p=fa[p])chl[p][x]=nt; } } } int slove(){ read(mask);int temp=root;int len=strlen(s2); for(int i=0;i<len;i++){ int t=s2[i]-'A'; if(!chl[temp][t])return 0; temp=chl[temp][t]; } int res=querty(temp);mask=mask^res; return res; } char str[11]; int main(){ int n;scanf("%d",&n);cur=root=cnt=1;newnode(root,0); scanf("%s",s1+1);int len=strlen(s1+1); for(int i=1;i<=len;i++)built(s1[i]-'A',i); mask=0;int num=len; for(int i=1;i<=n;i++){ scanf("%s",str); if(str[0]=='Q')printf("%d\n",slove()); else{ read(mask);len=strlen(s2); for(int j=0;j<len;j++)num++,built(s2[j]-'A',num); } } }
2555: SubString
Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 4356 Solved: 1339
[Submit][Status][Discuss]
Description
懒得写背景了,给你一个字符串init,要求你支持两个操作
(1):在当前字符串的后面插入一个字符串
(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
你必须在线支持这些操作。
Input
第一行一个数Q表示操作个数
第二行一个字符串表示初始字符串init
接下来Q行,每行2个字符串Type,Str
Type是ADD的话表示在后面插入字符串。
Type是QUERY的话表示询问某字符串在当前字符串中出现了几次。
为了体现在线操作,你需要维护一个变量mask,初始值为0
读入串Str之后,使用这个过程将之解码成真正询问的串TrueStr。
询问的时候,对TrueStr询问后输出一行答案Result
然后mask=maskxorResult
插入的时候,将TrueStr插到当前字符串后面即可。
HINT:ADD和QUERY操作的字符串都需要解压
长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000
新加数据一组--2015.05.20
Output
Sample Input
2
A
QUERY B
ADD BBABBBBAAB
A
QUERY B
ADD BBABBBBAAB
Sample Output
0