【BZOJ 2555】 2555: SubString (SAM+LCT)
2555: SubString
Time Limit: 30 Sec Memory Limit: 512 MB
Submit: 2548 Solved: 762Description
懒得写背景了,给你一个字符串init,要求你支持两个操作
(1):在当前字符串的后面插入一个字符串
(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
你必须在线支持这些操作。Input
第一行一个数Q表示操作个数
第二行一个字符串表示初始字符串init
接下来Q行,每行2个字符串Type,Str
Type是ADD的话表示在后面插入字符串。
Type是QUERY的话表示询问某字符串在当前字符串中出现了几次。
为了体现在线操作,你需要维护一个变量mask,初始值为0
读入串Str之后,使用这个过程将之解码成真正询问的串TrueStr。
询问的时候,对TrueStr询问后输出一行答案Result
然后mask = mask xor Result
插入的时候,将TrueStr插到当前字符串后面即可。HINT:ADD和QUERY操作的字符串都需要解压
Output
Sample Input
2
A
QUERY B
ADD BBABBBBAAB
Sample Output
0
HINT
40 % 的数据字符串最终长度 <= 20000,询问次数<= 1000,询问总长度<= 10000
100 % 的数据字符串最终长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000
新加数据一组--2015.05.20
Source
【分析】
一开始都没想着用LCT,后来发现我的SAM的right数组一直都是要逆拓扑序求的。
在线的话,还要在线维护。把pre边看成一棵树,就是要支持link,cut操作的,求子树和的东西。
其实LCT我只会做路径的,不会做子树了。看了hzwer的代码。【然后好像是,其实也是维护了路径,就是link x和f 的时候就是把f到根的路径都加上val[x]
【ORZ欧颓果说用splay维护dfs序也可以啊?
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 600010 8 #define Maxl 3000010 9 10 struct node 11 { 12 int pre,son[30],step; 13 }t[Maxn*2]; 14 15 struct nnode 16 { 17 int son[2],fa,val,laz; 18 nnode() {son[0]=son[1]=fa=val=laz=0;} 19 }tr[Maxn*2]; 20 21 char s[Maxl]; 22 void init(int mask) 23 { 24 scanf("%s",s); 25 int l=strlen(s); 26 for(int i=0;i<l;i++) 27 { 28 mask=(mask*131+i)%l; 29 swap(s[i],s[mask]); 30 } 31 } 32 33 struct lct 34 { 35 void add(int x,int y) 36 { 37 if(x) tr[x].val+=y,tr[x].laz+=y; 38 } 39 bool is_root(int x) 40 { 41 return tr[tr[x].fa].son[0]!=x&&tr[tr[x].fa].son[1]!=x; 42 } 43 bool pushdown(int x) 44 { 45 int lc=tr[x].son[0],rc=tr[x].son[1]; 46 if(tr[x].laz) 47 { 48 add(lc,tr[x].laz);add(rc,tr[x].laz); 49 tr[x].laz=0; 50 } 51 } 52 void rot(int x) 53 { 54 int fa=tr[x].fa,yy=tr[fa].fa; 55 int w=tr[tr[x].fa].son[0]==x; 56 57 if(!is_root(fa)) 58 { 59 if(tr[yy].son[0]==fa) tr[yy].son[0]=x; 60 else tr[yy].son[1]=x; 61 }tr[x].fa=yy; 62 63 tr[fa].son[1-w]=tr[x].son[w]; 64 tr[tr[x].son[w]].fa=fa; 65 66 tr[x].son[w]=fa; 67 tr[fa].fa=x; 68 //upd(fa);//upd(x); 69 } 70 int q[2*Maxn]; 71 void pre(int x) 72 { 73 int tp=0; 74 while(!is_root(x)) q[++tp]=x,x=tr[x].fa; 75 q[++tp]=x; 76 for(int i=tp;i>=1;i--) pushdown(q[i]); 77 } 78 void splay(int x) 79 { 80 pre(x); 81 while(!is_root(x)) 82 { 83 int fa=tr[x].fa,yy=tr[fa].fa; 84 if(!is_root(fa)) 85 { 86 if((tr[yy].son[0]==fa)==(tr[fa].son[0]==x)) rot(fa); 87 else rot(x); 88 } 89 rot(x); 90 }//upd(x); 91 } 92 void access(int x) 93 { 94 int t=0; 95 while(x) 96 { 97 splay(x); 98 tr[x].son[1]=t; 99 t=x; 100 x=tr[x].fa; 101 } 102 } 103 /*void split(int x,int y) 104 { 105 make_root(x); 106 access(y); 107 splay(y); 108 }*/ 109 void link(int x,int f) 110 { 111 tr[x].fa=f; 112 access(f); 113 splay(f); 114 add(f,tr[x].val); 115 } 116 void cut(int x) 117 { 118 access(x);splay(x); 119 add(tr[x].son[0],-tr[x].val); 120 tr[tr[x].son[0]].fa=0; 121 tr[x].son[0]=0; 122 } 123 }lct; 124 125 int mask; 126 struct sam 127 { 128 int last,tot; 129 void extend(int k) 130 { 131 int np=++tot,p=last; 132 t[np].step=t[p].step+1; 133 tr[np].val=1; 134 while(p&&!t[p].son[k]) 135 { 136 t[p].son[k]=np; 137 p=t[p].pre; 138 } 139 if(!p) t[np].pre=1,lct.link(np,1); 140 else 141 { 142 int q=t[p].son[k]; 143 if(t[q].step==t[p].step+1) t[np].pre=q,lct.link(np,q); 144 else 145 { 146 int nq=++tot;//upd(tot); 147 t[nq].step=t[p].step+1; 148 memcpy(t[nq].son,t[q].son,sizeof(t[nq].son)); 149 t[nq].pre=t[q].pre; 150 lct.link(nq,t[nq].pre); 151 t[q].pre=t[np].pre=nq; 152 lct.cut(q);lct.link(q,nq);lct.link(np,nq); 153 while(p&&t[p].son[k]==q) 154 { 155 t[p].son[k]=nq; 156 p=t[p].pre; 157 } 158 } 159 } 160 last=np; 161 } 162 void add() 163 { 164 init(mask); 165 int l=strlen(s); 166 for(int i=0;i<l;i++) extend(s[i]-'A'+1); 167 } 168 int query() 169 { 170 init(mask); 171 int nw=1,l=strlen(s); 172 for(int i=0;i<l;i++) 173 { 174 int ind=s[i]-'A'+1; 175 if(!t[nw].son[ind]) return 0; 176 nw=t[nw].son[ind]; 177 } 178 lct.splay(nw); 179 return tr[nw].val; 180 } 181 }sam; 182 183 char ss[10]; 184 185 int main() 186 { 187 int q; 188 scanf("%d",&q); 189 sam.tot=sam.last=1; 190 scanf("%s",s); 191 int l=strlen(s); 192 for(int i=0;i<l;i++) sam.extend(s[i]-'A'+1); 193 while(q--) 194 { 195 scanf("%s",ss); 196 if(ss[0]=='A') sam.add(); 197 else 198 { 199 int ans=sam.query(); 200 printf("%d\n",ans); 201 mask^=ans; 202 } 203 } 204 return 0; 205 }
2017-04-19 07:48:14