shift-and 字符串匹配\雾
我们用 bitset
按位维护字符是否出现过。每次按照偏移量 &
起来即可求出哪些位置出现过子串。
(成功手写 bitset
写挂)
#include<cstdio>
#include<cstring>
#include<iostream>
#define R register int
using namespace std;
namespace Luitaryi {
char B[1<<23],*E=B,*T=B;
#define getchar() (E==T&&(T=(E=B)+fread(B,1,1<<23,stdin),E==T)?EOF:*E++)
inline int g() { R x=0,f=1;
register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
}
inline void g(char* str) {
register char s; while(!isdigit(s=getchar()));
do *str++=s; while(isdigit(s=getchar())); *str='\0';
}
const int N=1000010;
#define u32 unsigned
#define popcount(x) (tab[x>>16]+tab[x&65535])
int Cas,t,n,m,op,tab[65536];
char s[N];
struct bitset {
u32 v[N/32+5];
inline void reset() {for(R i=0;i<=t;++i) v[i]=0;}
inline bool test(int x) {return v[x>>5]>>(x&31)&1;}
inline void set(int x,bool y)
{if((v[x>>5]>>(x&31)&1)^y) v[x>>5]^=1u<<(x&31);}
inline void flip(int x) {v[x>>5]^=1u<<(x&31);}
inline void shl(int l,int len) {
R L=len>>5,res=len&31,rev=(32-res)&31,p=l>>5;
for(R i=l,lim=(p<<5)+31;i<=lim;++i) set(i,test(i+len));
for(R i=p+1;i<=t;++i) {
v[i]=v[i+L]>>res;
if(rev) v[i]|=v[i+L+1]<<rev;
}
}
inline void shr(int l,int len) {
R L=len>>5,res=len&31,rev=(32-res)&31,p=l>>5;
v[t+L+1]=0;
for(R i=t;i>p;--i) {
if(rev) v[i+L+1]|=v[i]>>rev;
v[i+L]=v[i]<<res;
} for(R i=(p<<5)+31;i>=l;--i) set(i+len,test(i));
}
inline void cpy(int l,int r,const bitset& src)
{for(R i=l;i<=r;++i) v[i]=src.v[i];}
inline void And(int l,int r,const bitset& src)
{for(R i=l;i<=r;++i) v[i]&=src.v[i];}
inline void shift(int l,int r) {//左移一位
for(R i=r;i>=l;--i) {
v[i]<<=1;
if(i&&(v[i-1]>>31&1)) v[i]|=1;
}
}
inline int count(int l,int r) {
R p=l>>5,q=r>>5,ret=0;
if(p==q) {
for(R i=l;i<=r;++i)
if(v[p]>>(i&31)&1) ++ret;
return ret;
}
for(R i=p+1;i<q;++i) ret+=__builtin_popcount(v[i]);
for(R i=l,lim=(p<<5)+31;i<=lim;++i) if(v[p]>>(i&31)&1) ++ret;
for(R i=q<<5;i<=r;++i) if(v[q]>>(i&31)&1) ++ret;
return ret;
}
}f[10],S;
inline void get() {
g(s),m=strlen(s);
for(R i=0;i<m;++i) s[i]-='0';
}
inline void ins(int p) {
for(R i=0;i<10;++i) f[i].shr(p,m);
for(R i=0;i<10;++i) for(R j=0;j<m;++j)
f[i].set(p+j,s[j]==i);
n+=m,t=n>>5;
}
inline void del(int l,int r) {
if(l==r) return ;
n-=r-l,t=n>>5;
for(R i=0;i<10;++i) f[i].shl(l,r-l);
}
inline int ask(int l,int r) {
if(r-l<m) return 0; --r;
R LL=l>>5,RR=r>>5;
S.cpy(LL,RR,f[s[0]]);
for(R i=1;i<m;++i)
S.shift(LL,RR),S.And(LL,RR,f[s[i]]);
return S.count(l+m-1,r);
}
inline void main() {
Cas=g(); for(R i=1,op,x,y;i<=Cas;++i) {
op=g(),x=g();
if(op==0) get(),ins(x);
if(op==1) y=g(),del(x,y);
if(op==2) y=g(),get(),printf("%d\n",ask(x,y));
}
}
} signed main() {Luitaryi::main(); return 0;}
2020.01.16