Query on a string 线段树
动态维护s1的所有区间内s2的个数
开始的想法是线段树区间保存有多少个完整的s2串,当成区间合并做,暂时没调出来bug:
#include<bits/stdc++.h> #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<set> #include<map> #include<vector> #include<iomanip> using namespace std; #define ll long long #define ull unsigned long long #define pb push_back #define FOR(a) for(int i=1;i<=a;i++) const int inf=0x3f3f3f3f; const ll Linf=9e18; const int maxn=1e5+7; const ll mod=100003; const double eps=1e-6; /******************************************************/ namespace fastIO{ #define BUF_SIZE 100000 #define OUT_SIZE 100000 #define ll long long //fread->read bool IOerror=0; inline char nc(){ static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE; if (p1==pend){ p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin); if (pend==p1){IOerror=1;return -1;} //{printf("IO error!\n");system("pause");for (;;);exit(0);} } return *p1++; } inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';} inline void read(int &x){ bool sign=0; char ch=nc(); x=0; for (;blank(ch);ch=nc()); if (IOerror)return; if (ch=='-')sign=1,ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; if (sign)x=-x; } inline void read(ll &x){ bool sign=0; char ch=nc(); x=0; for (;blank(ch);ch=nc()); if (IOerror)return; if (ch=='-')sign=1,ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; if (sign)x=-x; } inline void read(double &x){ bool sign=0; char ch=nc(); x=0; for (;blank(ch);ch=nc()); if (IOerror)return; if (ch=='-')sign=1,ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; if (ch=='.'){ double tmp=1; ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0'); } if (sign)x=-x; } inline void read(char *s){ char ch=nc(); for (;blank(ch);ch=nc()); if (IOerror)return; for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch; *s=0; } inline void read(char &c){ for (c=nc();blank(c);c=nc()); if (IOerror){c=-1;return;} } #undef OUT_SIZE #undef BUF_SIZE }; using namespace fastIO; /*****************************************************/ int n;int len,len2; char s1[maxn],s2[maxn]; struct NODE{ int l,r; int val; }ST[maxn<<2]; void pushup(int rt){ ST[rt].val=ST[rt<<1].val+ST[rt<<1|1].val; int flag=0; for(int l=len2-1;l>=1;l--){ if(ST[rt<<1].r-ST[rt<<1].l+1<l ||ST[rt<<1|1].r-ST[rt<<1|1].l+1<len2-l )continue; int pos=1; int ok=1; //这个分配是否可行 int r=len2-l; //左区间l个右区间r个 for(int i= ST[rt<<1].r-l+1 ;i<=ST[rt<<1].r;i++){ if(s1[i]==s2[pos]){ pos++; }else{ ok=0;break; } } if(ok==0)continue; for(int i=ST[rt<<1|1].l;i<=ST[rt<<1|1].l + r-1;i++){ if(s1[i]==s2[pos]){ pos++; if(pos>len2){ break; } }else{ ok=0;break; } } if(ok){flag++;} } if(flag)ST[rt].val+=flag; } void build(int l,int r,int rt){ ST[rt].l=l;ST[rt].r=r;ST[rt].val=0; if(l==r){return;} int m=l+r>>1; build(l,m,rt<<1);build(m+1,r,rt<<1|1);pushup(rt); } void update(int a,char b,int l,int r,int rt){ if(l==r){s1[a]=b;return;} int m=l+r>>1; if(a<=m)update(a,b,l,m,rt<<1); else update(a,b,m+1,r,rt<<1|1); pushup(rt); } int query(int a,int b,int l,int r,int rt){ if(r<a || l>b)return 0; if(a<=l && b>=r){ return ST[rt].val; } int m=l+r>>1; int ret=0; if(a<=m)ret+=query(a,b,l,m,rt<<1); if(b>m)ret+=query(a,b,m+1,r,rt<<1|1); int flag=0; if(a<=m && b>m && b-a+1>=len2){ int pos=1; for(int l1=len2-1;l1>=1;l1--){ int r1=len2-l1; //左区间l1个右区间r1个 if(ST[rt<<1].r-ST[rt<<1].l+1<l1 ||ST[rt<<1|1].r-ST[rt<<1|1].l+1<r1 )continue; int ok=1; for(int i=ST[rt<<1].r-l1+1;i<=ST[rt<<1].r;i++){ if(s1[i]==s2[pos]){ pos++; }else{ ok=0;break; } } if(!ok)continue; for(int i=ST[rt<<1|1].l;i<=ST[rt<<1|1].l+r1-1;i++){ if(s1[i]==s2[pos]){ pos++; if(pos>len2){break;} }else{ ok=0;break; } } if(ok){ flag++; } } } if(flag)ret+=flag; return ret; } char op[2]; int main(){ int T;read(T); //scanf("%d",&T); while(T--){ //scanf("%d",&n); read(n); //scanf("%s%s",s1+1,s2+1); read(s1+1);read(s2+1); len=strlen(s1+1); len2=strlen(s2+1); build(1,len,1); for(int i=1;i<=n;i++){ //scanf("%s",op); read(op); if(op[0]=='Q'){ int x,y; //scanf("%d%d",&x,&y); read(x);read(y); if(y-x+1<len2){ printf("0\n");continue; } printf("%d\n",query(x,y,1,len,1)); }else{ int x;char ch[2]; //scanf("%d%s",&x,ch); read(x);read(ch); if(ch[0]==s1[x])continue; update(x,ch[0],1,len,1); } } puts(""); } }一个简单的做法是单点0,1表示作为头是否可以匹配,这个好写多了
#include<bits/stdc++.h> #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<set> #include<map> #include<vector> #include<iomanip> using namespace std; #define ll long long #define ull unsigned long long #define pb push_back #define FOR(a) for(int i=1;i<=a;i++) const int inf=0x3f3f3f3f; const ll Linf=9e18; const int maxn=1e5+7; const ll mod=100003; const double eps=1e-6; /******************************************************/ namespace fastIO{ #define BUF_SIZE 100000 #define OUT_SIZE 100000 #define ll long long //fread->read bool IOerror=0; inline char nc(){ static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE; if (p1==pend){ p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin); if (pend==p1){IOerror=1;return -1;} //{printf("IO error!\n");system("pause");for (;;);exit(0);} } return *p1++; } inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';} inline void read(int &x){ bool sign=0; char ch=nc(); x=0; for (;blank(ch);ch=nc()); if (IOerror)return; if (ch=='-')sign=1,ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; if (sign)x=-x; } inline void read(ll &x){ bool sign=0; char ch=nc(); x=0; for (;blank(ch);ch=nc()); if (IOerror)return; if (ch=='-')sign=1,ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; if (sign)x=-x; } inline void read(double &x){ bool sign=0; char ch=nc(); x=0; for (;blank(ch);ch=nc()); if (IOerror)return; if (ch=='-')sign=1,ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; if (ch=='.'){ double tmp=1; ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0'); } if (sign)x=-x; } inline void read(char *s){ char ch=nc(); for (;blank(ch);ch=nc()); if (IOerror)return; for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch; *s=0; } inline void read(char &c){ for (c=nc();blank(c);c=nc()); if (IOerror){c=-1;return;} } #undef OUT_SIZE #undef BUF_SIZE }; using namespace fastIO; /*****************************************************/ int len1,len2; char s1[maxn],s2[maxn]; char op[2],ch[2]; int x,y; int arr[maxn]; int same; struct NODE{ int val; }ST[maxn<<2]; //区间内有多少个头( void pushup(int rt){ST[rt].val=ST[rt<<1].val+ST[rt<<1|1].val;} void build(int l,int r,int rt){ if(l==r){ ST[rt].val=arr[l];return; } int m=l+r>>1; build(l,m,rt<<1);build(m+1,r,rt<<1|1);pushup(rt); } void update(int a,int b,int l,int r,int rt){ //区间[a,b]影响 if(l>b || r<a)return; if(l+len2-1>len1)return; if(l==r){ //计算s1[l]作为头是1还是0 int flag=1; for(int i=l;i<=l+len2-1;i++){ //if(i>len1){flag=0;break;} if(s1[i]!=s2[i-l+1]){ flag=0;break; } } if(flag)ST[rt].val=1;else ST[rt].val=0; return; } int m=l+r>>1; update(a,b,l,m,rt<<1);update(a,b,m+1,r,rt<<1|1); pushup(rt); } int query(int a,int b,int l,int r,int rt){ if(a<=l&&b>=r)return ST[rt].val; int m=l+r>>1,ret=0; if(a<=m)ret=query(a,b,l,m,rt<<1); if(b>m)ret+=query(a,b,m+1,r,rt<<1|1); return ret; } int main(){ int T; read(T); //scanf("%d",&T); while(T--){ int n; //scanf("%d",&n);scanf("%s%s",s1+1,s2+1); read(n); read(s1+1);read(s2+1); len1=strlen(s1+1);len2=strlen(s2+1); for(int i=1;i<=len1-len2+1;i++){ int flag=1; for(int j=i;j<=i+len2-1;j++){ if(s1[j]!=s2[j-i+1]){ flag=0;break; } } if(flag)arr[i]=1;else arr[i]=0; } build(1,len1,1); while(n--){ read(op); //scanf("%s",op); if(op[0]=='Q'){ read(x);read(y); //scanf("%d%d",&x,&y); if(y-x+1<len2){ printf("0\n");continue; } printf("%d\n",query(x,y-len2+1,1,len1,1)); }else{ read(x);read(ch); //scanf("%d%s",&x,ch); if(ch[0]!=s1[x])same=0; else same=1; if(same)continue; s1[x]=ch[0]; update(max(1,x-len2+1),x,1,len1,1); } } puts(""); } }