BZOJ 2555 SubString 后缀自动机+LCT
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2555
题意概述:给出一个初始字符串,支持两种操作:1、在这个字符串后面接上一个字符串;2、询问一个字符串在当前串中出现的次数。强制在线。
你发现这个东西没有更新就是SAM裸题。。。。。
有更新?SAM里面没问题,但是我们需要维护每个状态的right集合大小以及parent树的形态,于是就来一发LCT。
然后你发现这么直接写巨慢。。。。再来你发现parent树的根始终没有变过(滑稽),所以就没有mroot之类的操作的必要了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #include<set> 9 #include<map> 10 #include<vector> 11 #include<cctype> 12 using namespace std; 13 const int MAXN=3000005; 14 15 int Q,mask; char S[MAXN]; 16 struct Link_Cut_Tree{ 17 static const int maxn=1200005; 18 int np,ch[maxn][2],fa[maxn],w[maxn],add[maxn]; 19 Link_Cut_Tree(){ np=0; } 20 bool isrt(int x){ return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x; } 21 void link(int x,int d,int y){ ch[x][d]=y,fa[y]=x; } 22 void pushdown(int x){ 23 if(!add[x]) return; 24 int lc=ch[x][0],rc=ch[x][1]; 25 if(lc) add[lc]+=add[x],w[lc]+=add[x]; 26 if(rc) add[rc]+=add[x],w[rc]+=add[x]; 27 add[x]=0; 28 } 29 void rot(int x){ 30 int y=fa[x],z=fa[y]; 31 pushdown(y); pushdown(x); 32 int d=ch[y][0]==x; 33 if(!isrt(y)) link(z,ch[z][1]==y,x); fa[x]=z; 34 link(y,d^1,ch[x][d]); 35 link(x,d,y); 36 } 37 void splay(int x){ 38 pushdown(x); 39 while(!isrt(x)){ 40 int y=fa[x],z=fa[y]; 41 if(!isrt(y)) rot((ch[y][0]==x)==(ch[z][0]==y)?y:x); 42 rot(x); 43 } 44 } 45 void access(int x){ 46 int y=0; 47 while(x){ splay(x); ch[x][1]=y,y=x,x=fa[x]; } 48 } 49 void Cut(int x,int y){ access(x); splay(y); fa[y]=0; } 50 void update(int x){ 51 access(x); splay(x); 52 add[x]++,w[x]++; 53 } 54 int val(int x){ splay(x); return w[x]; } 55 }lct; 56 struct Suffix_Automaton{ 57 static const int maxn=1200005; 58 static const int sigma_sz=26; 59 int sz,last,to[maxn][sigma_sz],mx[maxn],pa[maxn]; 60 Suffix_Automaton(){ sz=last=1; memset(to[1],0,sizeof(to[1])); } 61 int newnode(){ 62 memset(to[++sz],0,sizeof(to[sz])); 63 mx[sz]=pa[sz]=0; 64 return sz; 65 } 66 void extend(int w){ 67 int p=last,np=newnode(); last=np; 68 mx[np]=mx[p]+1; 69 while(p&&!to[p][w]) to[p][w]=np,p=pa[p]; 70 if(!p){ pa[np]=1; lct.fa[np]=1; } 71 else{ 72 int q=to[p][w]; 73 if(mx[q]==mx[p]+1){ pa[np]=q; lct.fa[np]=q; } 74 else{ 75 int nq=newnode(); mx[nq]=mx[p]+1; 76 memcpy(to[nq],to[q],sizeof(to[q])); 77 pa[nq]=pa[q]; lct.Cut(pa[q],q); lct.fa[nq]=pa[nq]; 78 pa[q]=pa[np]=nq; lct.fa[q]=lct.fa[np]=nq; lct.w[nq]=lct.w[q]; 79 while(p&&to[p][w]==q) to[p][w]=nq,p=pa[p]; 80 } 81 } 82 lct.update(np); 83 } 84 int find(char *s){ 85 int now=1,i=0,n=strlen(s); 86 while(i<n){ 87 if(!to[now][s[i]-'A']) return 0; 88 now=to[now][s[i++]-'A']; 89 } 90 return now; 91 } 92 }sam; 93 94 void _scanf(char *s) 95 { 96 int cnt=0; 97 char c=getchar(); 98 while(!isalpha(c)) c=getchar(); 99 while(isalpha(c)) s[cnt++]=c,c=getchar(); 100 s[cnt]='\0'; 101 } 102 void data_in() 103 { 104 scanf("%d",&Q); _scanf(S); 105 int n=strlen(S); 106 for(int i=0;i<n;i++) sam.extend(S[i]-'A'); 107 } 108 void unzip(char *s,int m) 109 { 110 int n=strlen(s); 111 for(int i=0;i<n;i++) 112 m=(m*131+i)%n,swap(s[i],s[m]); 113 } 114 void work() 115 { 116 char op[10]; int ans,n,x; 117 for(int i=1;i<=Q;i++){ 118 _scanf(op);_scanf(S); 119 unzip(S,mask); 120 if(op[0]=='A'){ 121 n=strlen(S); 122 for(int i=0;i<n;i++) sam.extend(S[i]-'A'); 123 } 124 else if(op[0]=='Q'){ 125 x=sam.find(S); 126 printf("%d\n",ans=!x?0:lct.val(x)); 127 mask^=ans; 128 } 129 } 130 } 131 int main() 132 { 133 data_in(); 134 work(); 135 return 0; 136 }