http://www.tsinsen.com/ViewGProblem.page?gpid=A1484###
题解:
在线插入并不好做,我们将所有操作离线,变为删除操作。
每次询问的时候对于当前B串所在起始位置及其长度向上向下二分,然后查询区间内合法的当前A串内的匹配点即可。
用树状数组维护(不过我sb的写了线段树,后来才发现···)。
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #define maxn 200005 7 using namespace std; 8 char ch,a[maxn*3],b[maxn*3],s[maxn]; 9 int n,m,q,la,ra,lb,rb,lena,lenb,op[maxn],st[18][maxn],ans[maxn]; 10 int SA[maxn],rank[maxn],sum[maxn],height[maxn],t1[maxn],t2[maxn]; 11 bool ok; 12 void read(int &x){ 13 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 14 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 15 if (ok) x=-x; 16 } 17 struct seg{ 18 #define ls k<<1 19 #define rs (k<<1)+1 20 int val[maxn<<2]; 21 void build(int k,int l,int r){ 22 if (l==r){ 23 if (SA[l]<=ra) val[k]=1; 24 return; 25 } 26 int m=(l+r)>>1; 27 build(ls,l,m),build(rs,m+1,r); 28 val[k]=val[ls]+val[rs]; 29 } 30 void modify(int k,int l,int r,int x,int add){ 31 if (l==r){val[k]+=add;return;} 32 int m=(l+r)>>1; 33 if (x<=m) modify(ls,l,m,x,add); 34 else modify(rs,m+1,r,x,add); 35 val[k]=val[ls]+val[rs]; 36 } 37 int query(int k,int l,int r,int x,int y){ 38 if (l==x&&r==y) return val[k]; 39 int m=(l+r)>>1; 40 if (y<=m) return query(ls,l,m,x,y); 41 else if (x<=m) return query(ls,l,m,x,m)+query(rs,m+1,r,m+1,y); 42 else return query(rs,m+1,r,x,y); 43 } 44 }T; 45 void get_SA(){ 46 int *x=t1,*y=t2,tot=0; m=255; 47 for (int i=1;i<=n;i++) sum[x[i]=s[i]]++; 48 for (int i=1;i<=m;i++) sum[i]+=sum[i-1]; 49 for (int i=n;i>=1;i--) SA[sum[x[i]]--]=i; 50 for (int len=1;tot<n;len<<=1,m=tot){ 51 tot=0; 52 for (int i=n-len+1;i<=n;i++) y[++tot]=i; 53 for (int i=1;i<=n;i++) if (SA[i]>len) y[++tot]=SA[i]-len; 54 for (int i=1;i<=m;i++) sum[i]=0; 55 for (int i=1;i<=n;i++) sum[x[y[i]]]++; 56 for (int i=1;i<=m;i++) sum[i]+=sum[i-1]; 57 for (int i=n;i>=1;i--) SA[sum[x[y[i]]]--]=y[i]; 58 swap(x,y),x[SA[1]]=tot=1; 59 for (int i=2;i<=n;i++){ 60 if (y[SA[i]]!=y[SA[i-1]]||y[SA[i]+len]!=y[SA[i-1]+len]) tot++; 61 x[SA[i]]=tot; 62 } 63 } 64 for (int i=1;i<=n;i++) rank[i]=x[i]; 65 } 66 void get_height(){ 67 for (int i=1,j=0;i<=n;i++){ 68 if (rank[i]==1) continue; 69 while (s[i+j]==s[SA[rank[i]-1]+j]) j++; 70 height[rank[i]]=j; 71 if (j>0) j--; 72 } 73 } 74 void prepare(){ 75 for (int i=1;i<=n;i++) st[0][i]=height[i]; 76 for (int i=1;i<=17;i++) 77 for (int j=1;j<=n;j++){ 78 st[i][j]=st[i-1][j]; 79 if (j+(1<<(i-1))<=n) st[i][j]=min(st[i][j],st[i-1][j+(1<<(i-1))]); 80 } 81 T.build(1,1,n); 82 } 83 int calc(int l,int r){ 84 if (l>r) swap(l,r); 85 int t=0; l++; 86 if (l==r) return height[l]; 87 for (;l+(1<<t)<r;t++); 88 if (l+(1<<t)>r) t--; 89 return min(st[t][l],st[t][r-(1<<t)+1]); 90 } 91 int find(int s,int x,int op){ 92 int l,r,m; 93 if (op) l=s,r=n;else l=1,r=s; 94 while (l!=r){ 95 m=((l+r)>>1)+op; 96 if (calc(m,s)<x){ 97 if (op) r=m-1; 98 else l=m+1; 99 } 100 else{ 101 if (op) l=m; 102 else r=m; 103 } 104 } 105 return l; 106 } 107 int query(){ 108 int x=find(rank[lb],rb-lb+1,0),y=find(rank[lb],rb-lb+1,1); 109 return T.query(1,1,n,x,y); 110 } 111 int main(){ 112 scanf("%s%s",a+maxn,b+maxn); 113 la=ra=maxn,lb=rb=maxn; 114 for (;a[ra];ra++); ra--; 115 for (;b[rb];rb++); rb--; 116 read(q); 117 for (int i=1;i<=q;i++){ 118 read(op[i]); 119 if (op[i]==1) a[--la]=getchar(); 120 else if (op[i]==2) a[++ra]=getchar(); 121 else if (op[i]==3) b[--lb]=getchar(); 122 else if (op[i]==4) b[++rb]=getchar(); 123 } 124 for (int i=la;i<=ra;i++) s[++n]=a[i]; 125 lena=ra-la+1,la=1,ra=lena; 126 s[++n]='#'; 127 int tmp=n+1; 128 lenb=rb-lb+1; 129 for (int i=lb;i<=rb;i++) s[++n]=b[i]; 130 lb=tmp,rb=lb+lenb-1; 131 get_SA(),get_height(),prepare(); 132 for (int i=1;i<lenb;i++) T.modify(1,1,n,rank[ra--],-1); 133 for (int i=q;i>=1;i--){ 134 if (op[i]==1) T.modify(1,1,n,rank[la++],-1); 135 else if (op[i]==2) T.modify(1,1,n,rank[ra--],-1); 136 else if (op[i]==3) T.modify(1,1,n,rank[++ra],1),lb++; 137 else if (op[i]==4) T.modify(1,1,n,rank[++ra],1),rb--; 138 else ans[i]=query(); 139 } 140 for (int i=1;i<=q;i++) if (op[i]==5) printf("%d ",ans[i]); 141 return 0; 142 }