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;
}

  

posted @ 2017-01-16 00:59  Claris  阅读(366)  评论(0编辑  收藏  举报