You have two strings SS and TT in all capitals.
Now an efficient program is required to maintain a operation and support a query.
The operation C~i~chC i ch with given integer ii and capital letter chch, changes the ii-th character of SS into chch.
The query Q~i~jQ i j asks the program to find out, in the substring of SS from the ii-th character to the jj-th one, the total number of TT appearing.
Input Format
The first line contains an integer TT, indicating that there are TT test cases.
For each test case, the first line contains an integer N~(N \leq 100000)N (N≤100000).
The second line is the string S~(|S| \leq 100000)S (∣S∣≤100000) and the third line is the string T~(|T| \leq 10)T (∣T∣≤10).
Each of the following NN lines provide a operation or a query as above descriptions.
Output Format
For each query, output an integer correponding to the answer.
Output an empty line after each test case.
样例输入复制
1
5
AABBABA
AA
Q 1 3
C 6 A
Q 2 7
C 2 B
Q 1 5
样例输出复制
1
2
0
题目来源
编辑代码
题意:
给你一个A串一个B串,然后进行两种操作。
(1):给出p,q查询在A串中 p,q之间有多少B串(包括重叠的)。
(2):给出 p ch,将p位置的字符更改为ch。
分析:
这题的关键在于B串的字符少,不超过10,如果我们修改A串的某一个字符,那么对可能影响到答案只能是前后的10个,我们单独对其修改就行。我们用一个数组数组维护个数,如果匹配首字符标1,其他标0,那么如果我们改变l位置的字符,则前面l-blen+1的位置需要全部修改为0即可,然后跑一遍kmp匹配判断是否有出现新的匹配字符即可。
#include<iostream>
#include<string.h>
using namespace std;
typedef long long ll;
int read()//输入外挂
{
int ret=0, flag=0;
char ch;
if((ch=getchar())=='-')
flag=1;
else if(ch>='0'&&ch<='9')
ret = ch - '0';
while((ch=getchar())>='0'&&ch<='9')
ret=ret*10+(ch-'0');
return flag ? -ret : ret;
}
const int N = 100005;
int nxt[11];
char S[N], T[11];
int slen, tlen;
const int MAXN=100000+5;//最大元素个数
int n;//元素个数
int c[MAXN],vis[MAXN];//c[i]==A[i]+A[i-1]+...+A[i-lowbit(i)+1]
//返回i的二进制最右边1的值
int lowbit(int i)
{
return i&(-i);
}
//返回A[1]+...A[i]的和
ll sum(int x)
{
ll sum = 0;
while(x)
{
sum += c[x];
x -= lowbit(x);
}
return sum;
}
//令A[i] += val
void add(int x, ll val)
{
while(x <= slen) //注意这里的n,是树状数组维护的长度
{
c[x] += val;
x += lowbit(x);
}
}
void getNext()
{
int j, k;
j = 0;
k = -1;
nxt[0] = -1;
while(j < tlen)
if(k == -1 || T[j] == T[k])
{
nxt[++j] = ++k;
if (T[j] != T[k]) //优化
nxt[j] = k;
}
else
k = nxt[k];
}
/*
返回模式串在主串S中出现的次数 ,l表示从主串开始的字符,r表示结尾的字符,左开右闭
*/
int KMP_Count(int l,int r)
{
//cout<<l<<" "<<r<<endl;
for(int i=l; i<r-tlen+1; i++)
{
if(vis[i])
{
vis[i]=0;
add(i+1,-1);
}
}
int ans = 0;
int i=l, j = 0;
if(slen == 1 && r-l+1 == 1)
{
if(S[0] == T[0])
return 1;
else
return 0;
}
for(i=l; i < r;)
{
while(j > 0 && S[i] != T[j])
{
j = nxt[j];
}
if(S[i] == T[j])
j++;
i++;
if(j == tlen)
{
ans++;
//cout<<i-tlen+1<<"*"<<j<<endl;
add(i-tlen+1,1);
vis[i-tlen]=1;
j = nxt[j];///不可重叠的j=0
}
}
return ans;
}
int main()
{
int TT;
int l,r;
int n;
char ch,w;
TT=read();
while(TT--)
{
memset(c,0,sizeof(c));
memset(vis,0,sizeof(vis));
n=read();
scanf("%s%s",&S,&T);
tlen = strlen(T);
slen = strlen(S);
getNext();
KMP_Count(0,slen);
while(n--)
{
scanf(" %c",&ch);
if(ch=='Q')
{
l=read();
r=read();
if(r-l+1<tlen)
printf("0\n");
else
printf("%d\n",sum(r-tlen+1)-sum(l-1));
}
else
{
l=read();
scanf(" %c",&w);
if(S[l-1]!=w)
{
S[l-1]=w;
KMP_Count(max(0,l-1-tlen+1),min(slen-1,l-1+tlen-1)+1);
}
}
}
puts("");
}
return 0;
}