BZOJ2628 : JZPSTR
考虑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; }