考虑shift-and算法,那么只需要维护10个bitset即可,$f[i][j]$表示字符串$S$的第$j$位是否是字符$i$。
对于修改操作,直接暴力修改10个bitset即可,时间复杂度$O(\frac{|S|\sum}{32})$。
对于查询$T$在$S$中所有出现的位置,有$ans=ans<<1\ and\ f[T[i]]$,时间复杂度$O(\frac{|S||T|}{32})$。
#include<cstdio>
#include<cstring>
typedef unsigned int U;
const int N=1000010;
int T,op,x,y,i,j,n,cb,m,g[65536];char s[N];
inline int popcount(U x){return g[x>>16]+g[x&65535];}
struct BIT{
U v[N/32+5];
void clr(){for(int i=0;i<=cb;i++)v[i]=0;}
U get(int x){return v[x>>5]>>(x&31)&1;}
void set(int x,U y){if((v[x>>5]>>(x&31)&1)^y)v[x>>5]^=1U<<(x&31);}
void flip(int x){v[x>>5]^=1U<<(x&31);}
void shr(int x,int y){
int A=y>>5,B=y&31,C=(32-B)&31,D=x>>5;
v[cb+A+1]=0;
for(int i=cb;i>D;i--){
if(C)v[i+A+1]|=v[i]>>C;
v[i+A]=v[i]<<B;
}
for(int i=(D<<5)+31;i>=x;i--)set(i+y,get(i));
}
void shl(int x,int y){
int A=y>>5,B=y&31,C=(32-B)&31,D=x>>5,E=(D<<5)+31;
for(int i=x;i<=E;i++)set(i,get(i+y));
for(int i=D+1;i<=cb;i++){
v[i]=v[i+A]>>B;
if(C)v[i]|=v[i+A+1]<<C;
}
}
void copy(int x,int y,const BIT&p){for(int i=x;i<=y;i++)v[i]=p.v[i];}
void And(int x,int y,const BIT&p){for(int i=x;i<=y;i++)v[i]&=p.v[i];}
void shift(int x,int y){
for(int i=y;i>=x;i--){
v[i]<<=1;
if(i&&(v[i-1]>>31&1))v[i]|=1;
}
}
int count(int x,int y){
int A=x>>5,B=y>>5,C,ret=0;
if(A==B){
for(int i=x;i<=y;i++)if(v[A]>>(i&31)&1)ret++;
return ret;
}
for(int i=A+1;i<B;i++)ret+=popcount(v[i]);
C=(A<<5)+31;
for(int i=x;i<=C;i++)if(v[A]>>(i&31)&1)ret++;
C=B<<5;
for(int i=C;i<=y;i++)if(v[B]>>(i&31)&1)ret++;
return ret;
}
}f[10],S;
inline void getstr(){
scanf("%s",s);
m=strlen(s);
for(i=0;i<m;i++)s[i]-=‘0‘;
}
inline void ins(int x){
for(i=0;i<10;i++)f[i].shr(x,m);
for(i=0;i<10;i++)for(j=0;j<m;j++)f[i].set(x+j,s[j]==i);
n+=m;
cb=n>>5;
}
inline void del(int x,int y){
if(x==y)return;
n-=y-x;
cb=n>>5;
for(i=0;i<10;i++)f[i].shl(x,y-x);
}
inline int ask(int x,int y){
if(y-x<m)return 0;
y--;
int A=x>>5,B=y>>5;
S.copy(A,B,f[s[0]]);
for(i=1;i<m;i++)S.shift(A,B),S.And(A,B,f[s[i]]);
return S.count(x+m-1,y);
}
int main(){
for(i=1;i<65536;i++)g[i]=g[i>>1]+(i&1);
scanf("%d",&T);
while(T--){
scanf("%d%d",&op,&x);
if(op==0){
getstr();
ins(x);
}else if(op==1){
scanf("%d",&y);
del(x,y);
}else{
scanf("%d",&y);
getstr();
printf("%d\n",ask(x,y));
}
}
return 0;
}
原文:http://www.cnblogs.com/clrs97/p/6288320.html