bzoj 2555: SubString
阿新 • • 發佈:2018-04-13
char AR 維護 stdin cut 現實 字符串 return subst 了
Description
懶得寫背景了,給你一個字符串init,要求你支持兩個操作
(1):在當前字符串的後面插入一個字符串
(2):詢問字符串s在當前字符串中出現了幾次?(作為連續子串)
你必須在線支持這些操作。
Solution
思路比較直觀啊
首先沒有插入的話,預處理好每個點 \(|right|\) 就好了
如果有插入的話我們發現實際上就是維護一個子樹大小
每一次插入一個節點就相當於把父親到根路徑上的權值全部 \(+1\)
我們用 \(LCT\) 維護這個加邊刪邊和路徑加法的操作
每一次詢問就是先找到這個串對應的節點 \(x\),如果沒找到答案就是 \(0\),否則就是 \(|Right_x|\)
這題是有根樹,不需要 \(makeroot\) 操作,寫起來比較舒服
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+10;
namespace LCT{
int ch[N][2],fa[N],la[N],w[N];
inline bool isrt(int x){return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;}
inline void mark(int x,int t){la[x]+=t;w[x]+=t;}
inline void pushdown(int x){
if(!la[x])return ;
mark(ch[x][0],la[x]);mark(ch[x][1],la[x]);
la[x]=0;
}
inline void rotate(int x){
int y=fa[x];bool t=ch[y][1]==x;
ch[y][t]=ch[x][!t];fa[ch[y][t]]=y;
ch[x][!t]=y;fa[x]=fa[y];
if(!isrt(y))ch[fa[y]][ch[fa[y]][1 ]==y]=x;
fa[y]=x;
}
inline void Push(int x){
if(!isrt(x))Push(fa[x]);
pushdown(x);
}
inline void splay(int x){
Push(x);
while(!isrt(x)){
int y=fa[x],p=fa[y];
if(isrt(y))rotate(x);
else if((ch[p][0]==y)==(ch[y][0]==x))rotate(y),rotate(x);
else rotate(x),rotate(x);
}
}
inline void access(int x){
int y=0;
while(x)splay(x),ch[x][1]=y,x=fa[y=x];
}
inline void link(int x,int y){
fa[x]=y;access(y);splay(y);splay(x);mark(y,w[x]);
}
inline void cut(int x){
access(x);splay(x);mark(ch[x][0],-w[x]);fa[ch[x][0]]=0;ch[x][0]=0;
}
inline int query(int x){
splay(x);return w[x];
}
}
char s[N],op[10];int Q,mask=0;
inline void decode(){
int len=strlen(s),t=mask;
for(int j=0;j<len;j++){
t=(t*131+j)%len;
swap(s[j],s[t]);
}
}
int ch[N][27],fa[N],len[N],cur=1,cnt=1;
inline void ins(int c){
int p=cur;cur=++cnt;len[cur]=len[p]+1;LCT::w[cur]=1;
for(;p && !ch[p][c];p=fa[p])ch[p][c]=cur;
if(!p)fa[cur]=1,LCT::link(cur,1);
else{
int q=ch[p][c];
if(len[q]==len[p]+1)fa[cur]=q,LCT::link(cur,q);
else{
int nt=++cnt;len[nt]=len[p]+1;
memcpy(ch[nt],ch[q],sizeof(ch[q]));
LCT::cut(q);LCT::link(nt,fa[q]);LCT::link(q,nt);LCT::link(cur,nt);
fa[nt]=fa[q];fa[q]=fa[cur]=nt;
for(;p && ch[p][c]==q;p=fa[p])ch[p][c]=nt;
}
}
}
inline int solve(int len){
int p=1;
for(int i=0;i<len;i++){
int c=s[i]-'A';
if(ch[p][c])p=ch[p][c];
else return 0;
}
return LCT::query(p);
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
cin>>Q;
scanf("%s",s);
for(int i=0,le=strlen(s);i<le;i++)ins(s[i]-'A');
while(Q--){
scanf("%s%s",op,s);
decode();
int len=strlen(s),la;
if(op[0]=='A')for(int i=0;i<len;i++)ins(s[i]-'A');
else printf("%d\n",la=solve(len)),mask^=la;
}
return 0;
}
bzoj 2555: SubString