[BZOJ2555]SubString(后缀自动机+lct)
2017-04-04 08:42
375 查看
题目描述
传送门题解
询问每一个字符串出现过几次,实际上就是将这个字符串在后缀自动机上匹配,然后查询最终匹配到的那个点的right集合的大小又因为是在线的,pre指针经常会变化,所以把pa树用lct维护一下
维护lct的时候不要维护子树和,而应该连上一个点就将它一直到根的路径上的点都加上这个点的权,断开一个点就减去这个点的权,这样维护一棵有根树
代码
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define N 3000005 int n,len,ans; char opt[10],s ; int f ,ch [2],size ,delta ,stack ; int son [30],pre ,step ,root,last,sz,p,np,q,nq; //--------------------init---------------------- void init(int mask) { int len=strlen(s); for (int i=0;i<len;++i) { mask=(mask*131+i)%len; char t=s[i]; s[i]=s[mask]; s[mask]=t; } } //--------------------lct----------------------- bool isroot(int x) { return ch[f[x]][0]!=x&&ch[f[x]][1]!=x; } int get(int x) { return ch[f[x]][1]==x; } void pushdown(int x) { if (x&&delta[x]) { if (ch[x][0]) size[ch[x][0]]+=delta[x],delta[ch[x][0]]+=delta[x]; if (ch[x][1]) size[ch[x][1]]+=delta[x],delta[ch[x][1]]+=delta[x]; delta[x]=0; } } void rotate(int x) { int old=f[x],oldf=f[old],wh=get(x); if (!isroot(old)) ch[oldf][ch[oldf][1]==old]=x; f[x]=oldf; ch[old][wh]=ch[x][wh^1]; if (ch[old][wh]) f[ch[old][wh]]=old; ch[x][wh^1]=old; f[old]=x; } void splay(int x) { int top=0;stack[++top]=x; for (int i=x;!isroot(i);i=f[i]) stack[++top]=f[i]; for (int i=top;i;--i) pushdown(stack[i]); for (int fa;!isroot(x);rotate(x)) if (!isroot(fa=f[x])) rotate((get(x)==get(fa))?fa:x); } void access(int x) { int t=0; for (;x;t=x,x=f[x]) { splay(x); ch[x][1]=t; } } void link(int x,int y) { f[y]=x; access(x); splay(x); size[x]+=size[y],delta[x]+=size[y]; } void cut(int x,int y) { access(y); splay(y); size[x]-=size[y];delta[x]-=size[y]; ch[y][0]=f[x]=0; } int find(int x) { access(x); splay(x); while (ch[x][0]) x=ch[x][0]; return x; } //--------------------sam----------------------- void extend(int i) { int x=s[i]-'A'; p=last;np=++sz;last=np; step[np]=step[p]+1; while (p&&!son[p][x]) { son[p][x]=np; p=pre[p]; } if (!p) { pre[np]=root; f[np]=root; } else { q=son[p][x]; if (step[q]==step[p]+1) { pre[np]=q; f[np]=q; } else { nq=++sz; step[nq]=step[p]+1; memcpy(son[nq],son[q],sizeof(son[q])); pre[nq]=pre[q];link(pre[q],nq); while (son[p][x]==q) { son[p][x]=nq; p=pre[p]; } cut(pre[q],q); pre[q]=nq;link(nq,q); pre[np]=nq;link(nq,np); } } access(np); splay(np); ++size[np];++delta[np]; } int sam() { p=root; for (int i=0;i<len;++i) { int x=s[i]-'A'; p=son[p][x]; } if (!p) return 0; access(p); splay(p); return size[p]; } //--------------------main----------------------- int main() { scanf("%d",&n); scanf("%s",s);len=strlen(s); root=last=++sz; for (int i=0;i<len;++i) extend(i); int mask=0; while (n--) { scanf("%s",opt); scanf("%s",s);len=strlen(s); init(mask); if (opt[0]=='A') { for (int i=0;i<len;++i) extend(i); } else { ans=sam(); printf("%d\n",ans); mask^=ans; } } }
相关文章推荐
- bzoj 2555: SubString 后缀自动机+LCT
- [BZOJ2555][LCT][后缀自动机]SubString
- 后缀自动机 + LCT 【bzoj2555】SubString
- BZOJ2555:SubString 后缀自动机 LCT
- BZOJ 2555 Substring(后缀自动机+LCT子树维护)
- 【BZOJ2555】SubString 后缀自动机+LCT
- [BZOJ]2555 Substring 后缀自动机&LCT
- bzoj 2555: SubString 后缀自动机+lct
- 字符串(LCT,后缀自动机):BZOJ 2555 SubString
- BZOJ 2555 SubString LCT 后缀自动机
- 【bzoj2555】SubString LCT+后缀自动机
- 【后缀自动机+LCT】BZOJ2555[SubString]题解
- [后缀自动机 LCT] BZOJ 2555 SubString
- bzoj 2555 SubString 后缀自动机 LCT
- BZOJ 2555: SubString 后缀自动机 LCT
- bzoj2555 SubString(后缀自动机+LCT)
- 【bzoj2555】SubString 后缀自动机+LCT
- BZOJ 2555 SubString 后缀自动机+LCT
- bzoj 2555: SubString 后缀自动机+LCT
- [后缀自动机][LCT] BZOJ 2555: SubString