开始时间:19:40
完成时间:21:00
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2555
题目大意:(1):在当前字符串的后面插入一个字符串
(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
题解:最近在写后缀自动机,求一个字符串中出现了几次就相当与其right集合大小,直接上parent树,因为后缀自动机构造特性,可能在parent树改变边,于是用lct维护;
代码:
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #define maxn 1200005 7 #define maxl 3000005 8 using namespace std; 9 int q,n,tot,root,last,mark,m,ri[maxn],lazy[maxn]; 10 char st[maxl]; 11 char ss[20]; 12 struct data{ 13 int fa[maxn],son[maxn][2]; 14 int isroot(int x) {return (son[fa[x]][0]!=x && son[fa[x]][1]!=x);} 15 int which(int x){return son[fa[x]][1]==x;} 16 void change(int x,int k){ ri[x]+=k; lazy[x]+=k;} 17 void pushdown(int x) 18 { 19 if (!lazy[x]) return; 20 if (son[x][1]) change(son[x][1],lazy[x]); 21 if (son[x][0]) change(son[x][0],lazy[x]); 22 lazy[x]=0; 23 } 24 void relax(int x){if (!isroot(x)) relax(fa[x]); pushdown(x);} 25 void turn(int x){ 26 int y=fa[x],wx=which(x),wy=which(y); 27 if (!isroot(y)) son[fa[y]][wy]=x; fa[x]=fa[y]; 28 son[y][wx]=son[x][1-wx]; fa[son[x][1-wx]]=y; 29 son[x][1-wx]=y; fa[y]=x; 30 } 31 void splay(int x) 32 { 33 relax(x); 34 while (!isroot(x)) 35 { 36 if (isroot(fa[x])) turn(x); 37 else if (which(x)==which(fa[x])) turn(fa[x]),turn(x); 38 else turn(x),turn(x); 39 } 40 } 41 void access(int x) 42 { 43 for (int p=0; x; x=fa[x]){ splay(x); son[x][1]=p; p=x;} 44 } 45 void link(int x,int y){ 46 fa[x]=y; access(y); splay(y); change(y,ri[x]); 47 } 48 void cut(int x) 49 { 50 access(x); splay(x); change(son[x][0],-ri[x]); fa[son[x][0]]=0; son[x][0]=0; 51 } 52 }lct; 53 struct date{ 54 int fa[maxn],son[maxn][26],val[maxn]; 55 void prepare(){root=tot=last=1;} 56 int newnode(int x){val[++tot]=x; return tot;} 57 void extend(int x) 58 { 59 int p=last,np=newnode(val[p]+1);ri[np]=1;last=np; 60 for (; p&&!son[p][x]; p=fa[p]) son[p][x]=np; 61 if (!p) fa[np]=root,lct.link(np,root); 62 else 63 { 64 int q=son[p][x]; 65 if (val[q]==val[p]+1){fa[np]=q; lct.link(np,q);} 66 else 67 { 68 int nq=newnode(val[p]+1);ri[nq]=0; 69 memcpy(son[nq],son[q],sizeof(son[q])); 70 fa[nq]=fa[q]; lct.cut(q),lct.link(nq,fa[nq]); 71 fa[q]=fa[np]=nq; lct.link(q,nq),lct.link(np,nq); 72 for (; p && son[p][x]==q; p=fa[p]) son[p][x]=nq; 73 } 74 } 75 } 76 void build() 77 {for (int i=1; i<=m; i++) extend(st[i]-'A');} 78 void query(){ 79 int x,y; 80 bool can=1; 81 x=root; 82 for (int i=1;i<=m;i++){ 83 y=st[i]-'A'; 84 if (!son[x][y]){ 85 can=0; 86 break; 87 }else{ 88 x=son[x][y]; 89 } 90 } 91 if (can==0||x==root) puts("0"); 92 else{ 93 lct.splay(x); 94 printf("%d ",ri[x]),mark^=ri[x]; 95 } 96 } 97 }SAM; 98 void unzip(){ 99 int temp=mark; 100 for (int i=1;i<=m;i++){ 101 temp=(temp*131+i-1)%m+1; 102 char t=st[i]; st[i]=st[temp],st[temp]=t,temp--; 103 } 104 } 105 int main() 106 { 107 scanf("%d ",&q);mark=0; 108 scanf("%s",st+1); m=strlen(st+1); 109 SAM.prepare(); 110 SAM.build(); 111 for (int i=1; i<=q; i++) 112 { 113 scanf("%s",ss);scanf("%s",st+1); m=strlen(st+1);unzip(); 114 if (ss[0]=='A') SAM.build(); 115 else SAM.query(); 116 } 117 }