BZOJ2555 SubString 后缀自动机+LCT/暴力
题意:给定一个字符串,维护:1、在当前字符串后面插入一个字符串 2、询问一个字符串在当前字符串中出现的次数。强制在线
题解:维护自动机,一个字符插入之后其祖先的出现次数全部++,这个可以拿LCT或者暴力来维护,链上修改单点查询。
#include <cstdio> #include <cstring> #include <cstdlib> #include <climits> #include <iostream> #include <algorithm> using namespace std; const int MAXK=26; const int MAXN=3000000+2; struct SAM{ int v,c; SAM *child[MAXK],*f; SAM(int _v):v(_v),c(0),f(0){ memset(child,0,sizeof(child));} }*root,*last=root=new SAM(0); int N,Q,mask; char S[MAXN],T[MAXN]; void Decode(char *S,int mask){ for(int i=0,j=strlen(S);i<j;i++){ mask=(mask*131+i)%j; swap(S[i],S[mask]); } } void Extend(SAM *&x,int c){ SAM *p=last,*np=new SAM(p->v+1); while(p && !p->child[c]) p->child[c]=np,p=p->f; if(!p) np->f=x; else{ SAM *q=p->child[c]; if(q->v==p->v+1) np->f=q; else{ SAM *nq=new SAM(p->v+1); memcpy(nq->child,q->child,sizeof(q->child)); nq->f=q->f,q->f=np->f=nq; while(p && p->child[c]==q) p->child[c]=nq,p=p->f; } } last=np; while(np) np->c++,np=np->f; } int Query(SAM *x,char *S){ SAM *y=x; for(int i=0,j=strlen(S);i<j;i++){ y=y->child[S[i]-'A']; if(!y) return 0; if(i==j-1) return y->c; } } int main(){ scanf("%d %s",&Q,S); for(int i=0,j=strlen(S);i<j;i++) Extend(root,S[i]-'A'); while(Q--){ scanf("%s",S); if(strstr(S,"ADD")){ scanf("%s",S),Decode(S,mask); for(int i=0,j=strlen(S);i<j;i++) Extend(root,S[i]-'A'); } if(strstr(S,"QUERY")){ scanf("%s",S),Decode(S,mask); int t=Query(root,S); printf("%d\n",t),mask^=t; } } return 0; }