题意:给出母串s和字符串T,Q次操作.
操作1:把s的第i个字符修改为ch.操作2:询问s[i,j]中,T出现了多少次?
Q,|s|<=1e5.|T|<=10.
令f[i]标记s[i]结尾能否匹配字符串T.对于查询操作只要query(l+len2-1,r)
因为还有修改操作,又因为|T|<=10 修改s中的一个字符 最多只有|T|个位置f[i]变化,暴力修改f[i].
f[i]的前缀和是变化的 用树状数组来维护即可.O(Q*|T|^2*logn).
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
const int N=1e5+20;
char s[N],t[N];
int c[N],f[N],fail[N],len1,len2;
int lowbit(int x){return x&(-x);}
void update(int x,int val)
{
for(int i=x;i<N;i+=lowbit(i))
c[i]+=val;
}
int query(int x)
{
int res=0;
for(int i=x;i>0;i-=lowbit(i))
res+=c[i];
return res;
}
void getfail(char *b)
{
int i=0,j=-1;
int len=strlen(b);
fail[0]=-1;
while(i<len)
{
while(j!=-1&&b[i]!=b[j]) j=fail[j];
if(b[++i]==b[++j]) fail[i]=j;
else fail[i]=j;
}
}
void kmp(char *a,char *b)
{
int i=0,j=0;
getfail(b);
int lena=strlen(a),lenb=strlen(b);
while(i<lena)
{
while(j!=-1&&a[i]!=b[j]) j=fail[j];
i++,j++;
if(j>=lenb)
{
f[i]=1;
update(i,1);
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(f,0,sizeof(f));
memset(c,0,sizeof(c));
int l,r,Q;
char c,op[5];
scanf("%d%s%s",&Q,s+1,t+1);
len1=strlen(s+1),len2=strlen(t+1);
kmp(s+1,t+1);
while(Q--)
{
scanf("%s",op);
if(op[0]=='Q')
{
scanf("%d%d",&l,&r);
printf("%d\n",query(r)-query(l+len2-2));
}
else
{
scanf("%d %c",&l,&c);
s[l]=c;
for(int i=l;i>=max(1,l-len2+1);i--)
{
bool flag=true;
for(int k=1;k<=len2;k++)
{
if(s[i+k-1]!=t[k])
{
flag=false;
break;
}
}
int pos=i+len2-1;
bool mk=f[pos]?true:false;
if(!mk&&flag)
f[pos]=1,update(pos,1);
else if(mk&&(!flag))
f[pos]=0,update(pos,-1);
}
}
}
printf("\n");
}
return 0;
}