动态维护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("");
}
}