BZOJ 2555 SubString (后缀自动机+LCT)
题目大意:
让你维护一个文本串,支持在末尾插入字符,以及查询某个模式串在其中出现了多少次
什么sd题
$LCT$动态维护$parent$树,再用[BJOI2014]大融合的方法维护子树大小就行了
不要像我一样把LCT打错了
另外猫琨说这道题字符集开到2就行了,数据里只有A和B
1 #include <cmath> 2 #include <vector> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #define N1 605000 7 #define S1 (N1<<1) 8 #define L1 3000100 9 #define ll long long 10 #define uint unsigned int 11 #define rint register int 12 #define dd double 13 #define il inline 14 #define inf 0x3f3f3f3f 15 #define idx(X) (X-'A') 16 using namespace std; 17 18 int gint() 19 { 20 int ret=0,fh=1;char c=getchar(); 21 while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} 22 while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} 23 return ret*fh; 24 } 25 const int seed=131; 26 int Q,len; 27 char str[L1]; 28 namespace LCT{ 29 int ch[S1][2],fa[S1],stk[S1],sz[S1],sum[S1],sta[S1],rev[S1],tp; 30 int idf(int x){return ch[fa[x]][0]==x?0:1;} 31 int isroot(int x){return (ch[fa[x]][0]==x||ch[fa[x]][1]==x)?0:1;} 32 void revers(int x){swap(ch[x][0],ch[x][1]);rev[x]^=1;} 33 void pushup(int x){sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+sz[x]+sta[x];} 34 void pushdown(int x){if(rev[x]){revers(ch[x][0]),revers(ch[x][1]),rev[x]^=1;}} 35 void rot(int x) 36 { 37 int y=fa[x],ff=fa[y],px=idf(x),py=idf(y); 38 if(!isroot(y)) ch[ff][py]=x;fa[x]=ff; 39 ch[y][px]=ch[x][px^1],fa[ch[x][px^1]]=y; 40 ch[x][px^1]=y,fa[y]=x; 41 pushup(y),pushup(x); 42 } 43 void splay(int x) 44 { 45 int y=x;stk[++tp]=x; 46 while(!isroot(y)){stk[++tp]=fa[y],y=fa[y];} 47 while(tp){pushdown(stk[tp--]);} 48 while(!isroot(x)) 49 { 50 y=fa[x]; 51 if(isroot(y)) rot(x); 52 else if(idf(x)==idf(y)) rot(y),rot(x); 53 else rot(x),rot(x); 54 } 55 pushup(x); 56 } 57 void access(int x) 58 { 59 for(int y=0;x;y=x,x=fa[x]){ 60 splay(x); 61 sz[x]-=sum[y]; 62 sz[x]+=sum[ch[x][1]]; 63 ch[x][1]=y,pushup(x); 64 } 65 } 66 void mkroot(int x){access(x),splay(x),revers(x);} 67 int findroot(int x) 68 { 69 access(x); 70 splay(x); 71 while(1){ 72 pushdown(x); 73 if(ch[x][0]) x=ch[x][0]; 74 else break;} 75 return x; 76 } 77 void link(int x,int y){ 78 mkroot(y); 79 if(findroot(x)!=y) fa[x]=y,sz[y]+=sum[x];} 80 void cut(int x,int y) 81 { 82 mkroot(y); 83 if(findroot(x)==y && !ch[y][1] && ch[x][0]==y && fa[y]==x) 84 ch[x][0]=fa[y]=0,pushup(x); 85 } 86 int query(int x,int rt) 87 { 88 mkroot(rt),access(x),splay(x); 89 return sum[x]-sum[ch[x][0]]; 90 } 91 }; 92 namespace SAM{ 93 int trs[S1][2],pre[S1],dep[S1],la,tot; 94 void init(){la=tot=1;} 95 void insert(int c) 96 { 97 int p=la,np=++tot,q,nq;la=np; 98 dep[np]=dep[p]+1; 99 LCT::sta[np]=1; 100 for(;p&&!trs[p][c];p=pre[p]) trs[p][c]=np; 101 if(!p){LCT::link(np,1);pre[np]=1;return;} 102 q=trs[p][c]; 103 if(dep[q]==dep[p]+1){ 104 LCT::link(np,q); 105 pre[np]=q; 106 }else{ 107 pre[nq=++tot]=pre[q]; 108 LCT::cut(q,pre[q]); 109 LCT::link(nq,pre[q]); 110 pre[q]=pre[np]=nq; 111 LCT::link(q,nq); 112 LCT::link(np,nq); 113 dep[nq]=dep[p]+1; 114 memcpy(trs[nq],trs[q],sizeof(trs[q])); 115 for(;p&&trs[p][c]==q;p=pre[p]) trs[p][c]=nq; 116 } 117 } 118 int find(int L) 119 { 120 int x=1; 121 for(int i=0;i<L;i++) 122 { 123 x=trs[x][idx(str[i])]; 124 if(!x) return 0; 125 } 126 return LCT::query(x,1); 127 } 128 }; 129 char op[10]; 130 int mask,tmp; 131 132 int main() 133 { 134 //freopen("t4.in","r",stdin); 135 scanf("%d",&Q); 136 scanf("%s",str+1); 137 len=strlen(str+1); 138 SAM::init(); 139 for(int i=1;i<=len;i++) SAM::insert(idx(str[i])); 140 for(int i=1;i<=Q;i++) 141 { 142 scanf("%s",op);scanf("%s",str); 143 len=strlen(str); 144 tmp=mask; 145 for(int j=0;j<len;j++){ 146 tmp=(tmp*seed+j)%len; 147 swap(str[j],str[tmp]);} 148 if(op[0]=='A'){ 149 //for(int j=0;j<3;j++) printf("%c",op[j]);printf(" "); 150 for(int j=0;j<len;j++) 151 SAM::insert(idx(str[j])); 152 }else{ 153 int ans=SAM::find(len); 154 printf("%d\n",ans); 155 mask^=ans; 156 //for(int j=0;j<5;j++) printf("%c",op[j]);printf(" "); 157 } 158 /*for(int j=0;j<len;j++) printf("%c",str[j]); 159 puts("");*/ 160 } 161 return 0; 162 }