http://www.tsinsen.com/A1484
在线插入并不好做,我们将所有操作离线,变为删除操作。
每次询问的时候对于当前B串所在起始位置及其长度向上向下二分,然后查询区间内合法的当前A串内的匹配点即可。用树状数组维护。
#include<bits/stdc++.h> using namespace std; const int maxlen=200015,maxm=200015,maxk=20; int tmp,sta,eda,stb,edb,len,m,w[maxm]; char a[maxlen*2],b[maxlen*2],s[maxlen]; struct Tbit{ int T[maxlen]; void modify(int x,int v){for (int p=x;p<=len;p+=p&-p) T[p]+=v;} int query(int l,int r){ int res=0; for (int p=l-1;p>=1;p-=p&-p) res-=T[p]; for (int p=r;p>=1;p-=p&-p) res+=T[p]; return res; } }bit; struct Tsuffix_array{ int sum[maxlen],sa[maxlen],rank[maxlen],tsa[maxlen],trank[maxlen]; bool cmp(int i,int j,int l){ if (i+l>len||j+l>len) return 0; return rank[i]==rank[j]&&rank[i+l]==rank[j+l]; } void suffix_sort(){ int m=255,p,i,j; for (i=0;i<=m;++i) sum[i]=0; for (i=1;i<=len;++i) ++sum[rank[i]=s[i]]; for (i=1;i<=m;++i) sum[i]+=sum[i-1]; for (i=len;i>=1;--i) sa[sum[rank[i]]--]=i; for (p=0,j=1;p<len;j<<=1,m=p){ for (p=0,i=len-j+1;i<=len;++i) tsa[++p]=i; for (i=1;i<=len;++i) if (sa[i]>j) tsa[++p]=sa[i]-j; for (i=0;i<=m;++i) sum[i]=0; for (i=1;i<=len;++i) ++sum[rank[tsa[i]]]; for (i=1;i<=m;++i) sum[i]+=sum[i-1]; for (i=len;i>=1;--i) sa[sum[rank[tsa[i]]]--]=tsa[i]; for (p=trank[sa[1]]=1,i=2;i<=len;++i) trank[sa[i]]=cmp(sa[i],sa[i-1],j)?p:++p; memcpy(rank,trank,sizeof(int)*(len+1)); } } int height[maxlen]; void get_height(){ for (int h=0,i=1;i<=len;++i){ if (rank[i]==1) continue; for (h?--h:0;s[i+h]==s[sa[rank[i]-1]+h];++h); height[rank[i]]=h; } } int fmn[maxk][maxlen]; void prepare(){ for (int i=2;i<=len;++i) fmn[0][i]=height[i]; for (int k=1;k<maxk;++k) for (int j=1<<k;j<=len;++j) fmn[k][j]=min(fmn[k-1][j],fmn[k-1][j-(1<<(k-1))]); } int LCP(int x,int y){ if (++x>y) return len-sa[y]+1; int k=log2(y-x+1); return min(fmn[k][y],fmn[k][x+(1<<k)-1]); } int calc_up(int pos,int lim){ int l=1,r=pos,res; while (l<=r){ int mid=(l+r)>>1; LCP(mid,pos)>=lim?r=(res=mid)-1:l=mid+1; } return res; } int calc_low(int pos,int lim){ int l=pos,r=len,res; while (l<=r){ int mid=(l+r)>>1; LCP(pos,mid)>=lim?l=(res=mid)+1:r=mid-1; } return res; } int query(){ int pos=rank[tmp+stb],lim=edb-stb+1; return bit.query(calc_up(pos,lim),calc_low(pos,lim)); } }SA; void init(){ sta=stb=maxlen;scanf("%s%s%d",a+maxlen,b+maxlen,&m); eda=maxlen+strlen(a+maxlen)-1;edb=maxlen+strlen(b+maxlen)-1; for (int i=1;i<=m;++i){ char c[2];scanf("%d",&w[i]); switch (w[i]){ case 1:scanf("%s",c);a[--sta]=c[0];break; case 2:scanf("%s",c);a[++eda]=c[0];break; case 3:scanf("%s",c);b[--stb]=c[0];break; case 4:scanf("%s",c);b[++edb]=c[0];break; default:break; } } for (int i=sta;i<=eda;++i) a[i-sta+1]=a[i];a[eda-sta+2]=0;eda=eda-sta+1;sta=1; for (int i=stb;i<=edb;++i) b[i-stb+1]=b[i];b[edb-stb+2]=0;edb=edb-stb+1;stb=1; for (int i=1;i<=eda;++i) s[++len]=a[i];s[++len]='#';tmp=len; for (int i=1;i<=edb;++i) s[++len]=b[i];s[len+1]=0; } vector<int> ans; void work(){ SA.suffix_sort();SA.get_height();SA.prepare(); for (int i=1;i<=eda-edb+1;++i) bit.modify(SA.rank[i],1); for (int tim=m;tim>=1;--tim) switch (w[tim]){ case 1:if (eda-sta+1>=edb-stb+1) bit.modify(SA.rank[sta],-1);++sta;break; case 2:if (eda-sta+1>=edb-stb+1) bit.modify(SA.rank[eda-(edb-stb+1)+1],-1);--eda;break; case 3:++stb;if (eda-sta+1>=edb-stb+1) bit.modify(SA.rank[eda-(edb-stb+1)+1],1);break; case 4:--edb;if (eda-sta+1>=edb-stb+1) bit.modify(SA.rank[eda-(edb-stb+1)+1],1);break; case 5:ans.push_back(SA.query());break; } for (int i=ans.size()-1;i>=0;--i) printf("%d ",ans[i]); } int main(){ init(); work(); return 0; }