2555: SubString[LCT+SAM]
2555: SubString
Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 2601 Solved: 780
[Submit][Status][Discuss]
Description
懶得寫背景了,給你一個字符串init,要求你支持兩個操作
(1):在當前字符串的後面插入一個字符串
(2):詢問字符串s在當前字符串中出現了幾次?(作為連續子串)
你必須在線支持這些操作。
Input
第一行一個數Q表示操作個數
第二行一個字符串表示初始字符串init
接下來Q行,每行2個字符串Type,Str
Type是ADD的話表示在後面插入字符串。
Type是QUERY的話表示詢問某字符串在當前字符串中出現了幾次。
為了體現在線操作,你需要維護一個變量mask,初始值為0
讀入串Str之後,使用這個過程將之解碼成真正詢問的串TrueStr。
詢問的時候,對TrueStr詢問後輸出一行答案Result
插入的時候,將TrueStr插到當前字符串後面即可。
HINT:ADD和QUERY操作的字符串都需要解壓
Output
Sample Input
2A
QUERY B
ADD BBABBBBAAB
Sample Output
0
HINT
40 % 的數據字符串最終長度 <= 20000,詢問次數<= 1000,詢問總長度<= 10000
100 % 的數據字符串最終長度 <= 600000,詢問次數<= 10000,詢問總長度<= 3000000
新加數據一組--2015.05.20
Source
Ctsc模擬賽By 潔妹
- 答案顯然是目標串狀態的right集合的大小,因為要在線我們可以用LCT來維護parent樹。也就是說每次將當前點到根節點路徑上的right +1。
#include<cstdio> #include<cstring> #include<iostream> using namespace std; //---------------------LCT---------------------- const int M=3e6+10; int n,m,fa[M],st[M],c[M][2]; bool rev[M]; int tag[M]; int val[M]; bool isroot(int x){ return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; } /*void update(int x){ val[x]=val[c[x][0]]+val[c[x][1]]+1; }*/ void opera(int x,int v){ if(x) tag[x]+=v,val[x]+=v; } void rotate(int x){ int y=fa[x],z=fa[y],l,r; l=(c[y][1]==x);r=l^1; if(!isroot(y)) c[z][c[z][1]==y]=x; fa[x]=z;fa[y]=x;fa[c[x][r]]=y; c[y][l]=c[x][r];c[x][r]=y; //update(y);update(x); } #define l c[x][0] #define r c[x][1] void pushdown(int x){ /*if(rev[x]){ rev[x]^=1;rev[l]^=1;rev[r]^=1; swap(l,r); }*/ if(tag[x]){ opera(l,tag[x]); opera(r,tag[x]); tag[x]=0; } } void splay(int x){ int top=0;st[++top]=x; for(int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i]; for(int i=top;i;i--) pushdown(st[i]); while(!isroot(x)){ int y=fa[x],z=fa[y]; if(!isroot(y)){ if((c[y][0]==x)^(c[z][0]==y)) rotate(x); else rotate(y); } rotate(x); } } void access(int x){ for(int t=0;x;x=fa[x]) splay(x),c[x][1]=t,t=x; } /*void evert(int x){ access(x);splay(x);rev[x]^=1; }*/ void link(int x,int y){ fa[x]=y;access(y);splay(y); //evert(x);fa[x]=y;splay(x); opera(y,val[x]); } /*void cut(int x,int y){ evert(x); access(y);splay(y); opera(y,-val[y]); c[y][0]=fa[c[y][0]]=0;//!!! }*/ void cut(int x){ access(x);splay(x);opera(l,-val[x]); c[x][0]=fa[c[x][0]]=0; } int find(int x){ access(x);splay(x); for(;l;x=l); return x; } #undef l #undef r //---------------------SAM---------------------- const int N=1.2e6+5; int p,q,np,nq; int last,cnt,len,mask; int l[N],par[N],tr[N][26]; int siz[N];char s[N]; inline void extend(int c){ p=last;np=last=++cnt;val[np]=1;l[np]=l[p]+1; for(;p&&!tr[p][c];tr[p][c]=np,p=par[p]); if(!p) par[np]=1,link(np,1); else{ q=tr[p][c]; if(l[p]+1==l[q]) par[np]=q,link(np,q); else{ nq=++cnt;l[nq]=l[p]+1;cut(q); memcpy(tr[nq],tr[q],sizeof tr[q]); par[nq]=par[q]; link(nq,par[q]); // siz[nq]=siz[q]; par[np]=par[q]=nq; link(np,nq);link(q,nq); for(;tr[p][c]==q;tr[p][c]=nq,p=par[p]); } } // for(;np;np=par[np]) siz[np]++; } inline void build(){ for(int i=0;i<len;i++) extend(s[i]-‘A‘); } inline int query(){ int p=1; for(int i=0,c;i<len;i++){ c=s[i]-‘A‘; if(!tr[p][c]) return 0; p=tr[p][c]; } splay(p); mask^=val[p]; return val[p]; } inline void decode(int mask){ len=strlen(s); for(int i=0;i<len;i++){ mask=(mask*131+i)%len; swap(s[mask],s[i]); } } int main(){ last=++cnt; scanf("%d",&m);scanf("%s",s);len=strlen(s); build(); for(char op[9];m--;){ scanf("%s%s",op,s);decode(mask); if(op[0]==‘A‘) build(); else printf("%d\n",query()); } return 0; }
2555: SubString[LCT+SAM]