2555:substring time limit:30 Sec Memory limit:512 MB
submit:1936 solved:551
[Submit] [Status] [Discuss] Description
Too lazy to write the background, give you a string init, ask you to support two operations
(1): Inserts a string after the current string
(2): How many times does the query string s appear in the current string? (as continuous substring)
You must support these operations online.
Input
The first line a number q indicates the number of operations
The second line is a string representing the initial string init
Next Q line, 2 strings per line Type,str
Type is the add word that is inserted after the string.
Type is a query that asks for a string that appears several times in the current string.
In order to represent the online operation, you need to maintain a variable mask with an initial value of 0
After reading the string str, use this procedure to decode it into a string truestr that is actually queried.
When asked, output a line answer to TRUESTR after query result
Then mask = Mask xor Result
When inserting, insert Truestr after the current string.
Both the Hint:add and query operation strings need to be decompressed
Outputsample Input2
A
QUERY B
ADD Bbabbbbaab
Sample Output0
HINT
40% of data string final length <= 20000, number of queries <= 1000, total length of inquiry <= 10000
100% of data string final length <= 600000, number of queries <= 10000, total length of inquiry <= 3000000
A group of new data and--2015.05.20
Source
CTSC Simulation by Jie Mei
Solution
The most difficult problem in the paper, thank ABCLZR Captain's help.
The number of occurrences of a string in a template string is obviously $| Right (s) |$, then this method is the number of leaf nodes in the subtree of the $parent$ tree.
The brute force query is a single $o (N) $, the overall $o (N^{2}) $, so to utilize the data structure LCT maintenance, implement query $o (LOGN) $.
While the SAM is being built, the corresponding link/cut operation is performed on the LCT, and the contribution is subtracted when cut.
The sample is a bit weak, and I have a test point:
5 ababaquery abquery aadd babquery abquery A
Input
2 3 3 4
OutputCode
#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespacestd;#defineMAXN 1200010CharS[MAXN];intN,q,m,ans,mask;inlinevoidRead () {stringstr=s+1; intmask=Mask; for(intI=0; I<str.length (); i++) {Mask= (mask*131+i)%str.length (); Swap (Str[i],str[mask]); } for(intI=0, tot=0; I<str.length (); i++) s[++tot]=str[i];}namespacelct{intfa[maxn],ch[maxn][2],VAL[MAXN],TAG[MAXN]; InlineBOOLIs_root (intx) {return!fa[x] | | ch[fa[x]][1]!=x&&ch[fa[x]][0]!=x;} InlinevoidADD (intXintV) {if(!x)return; val[x]+=v,tag[x]+=v;} InlinevoidPushdown (intx) {if(Tag[x]) ADD (ch[x][0],tag[x]), ADD (ch[x][1],tag[x]), tag[x]=0;} InlinevoidRotate (intx) {inty=fa[x],w=ch[y][1]==x,z=Fa[y]; CH[Y][W]=ch[x][w^1]; if(ch[x][w^1]) fa[ch[x][w^1]]=y; if(ch[z][0]==y) ch[z][0]=x;Else if(ch[z][1]==y) ch[z][1]=x; FA[X]=fa[y]; Fa[y]=x; ch[x][w^1]=y; } intSTACK[MAXN]; InlinevoidSplay (intx) {inttop=0, T=x,y; stack[++top]=x; while(!is_root (t)) stack[++top]=t=Fa[t]; while(top) Pushdown (stack[top--]); while(!is_root (x)) {y=Fa[x]; if(!is_root (y))if((ch[fa[y]][0]==y) ^ (ch[y][0]==x)) Rotate (x); ElseRotate (y); Rotate (x); }} inlinevoidAccess (intx) { for(inty=0; X Y=X,X=FA[X]) splay (x), ch[x][1]=y;} InlinevoidLink (intXintY) {fa[x]=y; Access (y); Splay (y); ADD (Y,val[x]);} InlinevoidCut (intx) {Access (x); Splay (x); ADD (ch[x][0],-VAL[X]); fa[ch[x][0]]=0, ch[x][0]=0;}}using namespaceLCT;namespacesam{intson[maxn][ -],LEN[MAXN],PAR[MAXN]; intRoot,last,sz; InlinevoidInit () {root=last=sz=1;} InlinevoidExtend (intc) {intcur=++sz,p=Last ; Len[cur]=len[p]+1; lct::val[cur]=1; while(P &&!son[p][c]) son[p][c]=cur,p=Par[p]; if(!p) par[cur]=Root,lct::link (cur,root); Else { intq=Son[p][c]; if(len[p]+1==LEN[Q]) par[cur]=Q,lct::link (CUR,Q); Else { intnq=++sz; memcpy (Son[nq],son[q],sizeof(Son[nq])); LEN[NQ]=len[p]+1, par[nq]=Par[q]; Lct::link (Nq,par[nq]); while(P && son[p][c]==q) son[p][c]=nq,p=Par[p]; Par[cur]=par[q]=NQ; Lct::cut (q); Lct::link (CUR,NQ); Lct::link (Q,NQ); }} last=cur; } InlinevoidBuild () {Init (); for(intI=1; i<=n; i++) Extend (s[i]-'A'+1);} InlinevoidInsert () {read (); M=strlen (s+1); for(intI=1; i<=m; i++) Extend (s[i]-'A'+1); } InlineintQuery () {read (); M=strlen (s+1); intnow=Root; for(intI=1; i<=m; i++) if(!son[now][s[i]-'A'+1])return 0; Elsenow=son[now][s[i]-'A'+1]; Lct::splay (now); returnVal[now]; }}using namespaceSAM;intMain () {scanf ("%d",&Q); scanf ("%s", s+1); N=strlen (s+1); Sam::build (); while(q--) { Charopt[Ten]; scanf ("%s%s", opt+1, s+1); Switch(opt[1]) { Case 'A': Sam::insert (); Break; Case 'Q': printf ("%d\n", Ans=sam::query ()); Mask^=ans; Break; }//for (int i=1; i<=sz; i++) printf ("%d%d%d%d\n", I,ch[i][0],ch[i][1],val[i]); } return 0;}
Too long did not see LCT, appeared large forgotten, back a template can be mistaken, in fact, should first review LCT write this problem again.
"BZOJ-2555" SubString suffix automaton + linkcuttree