BZOJ 2555: SubString 后缀自动机+LCT
2016-12-30 18:33
381 查看
后缀自动机的经典模型,查询一个字符串出现了几次,我们可以联想一下在代码中并未体现的right数组,我们很容易发现,有几个right数组就代表着这个单词出现了几次,那么我们只要设法维护出来就好了,我们可以想到加一个单词在parent树中只对这个单词所在的链有影响,所以我们只要维护一个LCT把parent树维护出来就行了,每次新加节点将parent树对应的链的right+1就行了(据说这题不用LCT更快)
#include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cstring> #include<string> #include<iostream> #include<iomanip> #include<algorithm> using namespace std; struct splay { splay *fa,*ls,*rs; int add_mark,val; splay(int); void push_down(); void add(int v); }*null=new splay(0); splay :: splay(int _=0) { fa=ls=rs=null; add_mark=0; val=_; } void splay :: add(int v) { val+=v; add_mark+=v; } void splay :: push_down() { if(add_mark) { if(ls!=null) ls->add(add_mark); if(rs!=null) rs->add(add_mark); add_mark=0; } } void right(splay *x) { splay *y=x->fa; y->ls=x->rs; x->rs->fa=y; x->fa=y->fa; x->rs=y; if(y==y->fa->ls) y->fa->ls=x; else if(y==y->fa->rs) y->fa->rs=x; y->fa=x; } void left(splay *x) { splay *y=x->fa; y->rs=x->ls; x->ls->fa=y; x->fa=y->fa; x->ls=y; if(y==y->fa->ls) y->fa->ls=x; else if(y==y->fa->rs) y->fa->rs=x; y->fa=x; } void push_down(splay *x) { if(x==x->fa->ls || x==x->fa->rs) push_down(x->fa); x->push_down(); } void splaying(splay *x) { push_down(x); while(1) { splay *y=x->fa; splay *z=y->fa; if(x!=y->ls && x!=y->rs) break; if(y!=z->ls && y!=z->rs) { if(x==y->ls) right(x); else left(x); break; } if(x==y->ls) { if(y==z->ls) right(y); right(x); } else if(x==y->rs) { if(y==z->rs) left(y); left(x); } } } void access(splay *x) { splay *y=null; while(x!=null) { splaying(x); x->rs=y; y=x; x=x->fa; } } void cut(splay *x) { access(x); splaying(x); x->ls->fa=null; x->ls=null; } void link(splay *x,splay *y) { cut(x); x->fa=y; } struct sam { sam *parent,*son[26]; int max_len; splay *tree; sam(int _=0):parent(0x0),max_len(_) { memset(son,0,sizeof(son)); tree=new splay(0); } }*root=new sam,*last=root; void my_insert(int x) { sam *p=last; sam *np=new sam(p->max_len+1); while(p && !p->son[x]) { p->son[x]=np; p=p->parent; } if(!p) { np->parent=root; link(np->tree,root->tree); } else { sam *q=p->son[x]; if(p->max_len==q->max_len-1) { np->parent=q; link(np->tree,q->tree); } else { sam *nq=new sam(p->max_len+1); nq->parent=q->parent; link(nq->tree,q->parent->tree); memcpy(nq->son,q->son,sizeof(nq->son)); q->parent=nq;np->parent=nq; link(q->tree,nq->tree); link(np->tree,nq->tree); push_down(q->tree); nq->tree->val=q->tree->val; while(p && p->son[x]==q) { p->son[x]=nq; p=p->parent; } } } last=np; access(np->tree); splaying(np->tree); np->tree->add(1); } char s[1000000]; int search_ans() { sam *o=root; for(int i=0;s[i];i++) { if(!o->son[s[i]-'A']) return 0; o=o->son[s[i]-'A']; } push_down(o->tree); return o->tree->val; } void main_insert() { for(int i=0;s[i];i++) my_insert(s[i]-'A'); } void decode(int mask) { int i,n=strlen(s); for(i=0;i<n;i++) { mask=(mask*131+i)%n; swap(s[i],s[mask]); } } int main() { int n; scanf("%d",&n); scanf("%s",s); main_insert(); int mask=0; for(int i=1;i<=n;i++) { scanf("%s",s); if(s[0]=='A') { scanf("%s",s); decode(mask); main_insert(); } else if(s[0]=='Q') { scanf("%s",s); decode(mask); int ans=search_ans(); mask^=ans; printf("%d\n",ans); } } }
相关文章推荐
- bzoj 2555: SubString 后缀自动机+LCT
- bzoj 2555 SubString 后缀自动机 LCT
- BZOJ 2555: SubString [后缀自动机 LCT]
- BZOJ 2555: SubString 后缀自动机 LCT
- bzoj2555 SubString(后缀自动机+LCT)
- 【bzoj2555】SubString 后缀自动机+LCT
- [后缀自动机][LCT] BZOJ 2555: SubString
- [BZOJ2555]SubString(后缀自动机+LCT)
- BZOJ2555 SubString 后缀自动机+LCT
- bzoj 2555: SubString 后缀自动机+lct
- BZOJ2555 SubString 【后缀自动机 + LCT】
- 字符串(LCT,后缀自动机):BZOJ 2555 SubString
- 【bzoj2555】SubString LCT+后缀自动机
- [BZOJ2555]-SubString-后缀自动机+LCT维护parent树
- BZOJ 2555 SubString 后缀自动机+LCT
- [BZOJ2555][LCT][后缀自动机]SubString
- 后缀自动机 + LCT 【bzoj2555】SubString
- [BZOJ2555]SubString(后缀自动机+lct)
- BZOJ2555:SubString 后缀自动机 LCT
- bzoj 2555: SubString 后缀自动机+lct