题目大意,给予两个串,S和T, S很长,T很短(这个很重要), 有n次操作,操作分为两种形式, 一种是把S的第i个字符替换, 第二中是截取S中l到r的一段,求T在这段出现的次数。
思路:先构建一个线段树,所有节点初始化为0,然后对S和T进行kmp匹配,如果T在S中出现,就把T这次出现的T【0】位置,所对应的线段树节点变为1。
例如: S为‘ADADBBAD', T为’AD', 那么线段树的节点为1,0,1,0,0,0,1,0 。
那么对于每次查询,就是线段树中 sum(l, r)- sum(r-(len(s))+1 ,r),的值。
对于每次修改(假设修改了id位置的字符), 因为T的长度最多是10, 直接把S串中id-len(T) 到id, 这段字符取出,和T进行匹配,然后去修改线段树对应这段的数据就可以了。
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
#define Max_N (100000+100)
#define updata1 updata
int next1[20];
int tree[4*Max_N];
int len4;
void init(int n_) {
len4 = 1;
while (len4 < n_) len4 *= 2;
}
void updata(int k, int s)
{
int n = len4;
k += n - 1;
tree[k] = s;
while (k > 1) {
k = (k) / 2;
tree[k] = tree[2*k] + tree[2*k+1];
}
}
int query(int node, int l ,int r, int L, int R)
{
int mid = l + (r - l) / 2;
if (L > R) return 0;
if (R < l || L > r) return 0;
if (L <= l && r <= R) return tree[node];
return query(node*2, l, mid, L, R) + query(node*2+1, mid+1, r, L, R);
}
void kmp_pre(char x[], int m, int next1[])
{
int i, j;
j = next1[0] = -1;
i = 0;
while (i < m)
{
while(-1 != j && x[i] != x[j]) j = next1[j];
next1[++i] = ++j;
}
}
int num;
void KMP_Count(char x[], int len1, char y[], int len2)
{
int i, j;
int ans = 0;
i = j = 0;
num = 0;
while (i < len2) {
while (-1 != j && y[i] != x[j]) j = next1[j];
i++; j++;
if(j >= len1) {
j = next1[j];
updata(i - len1+1, 1);
}
}
return;
}
void KMP_Count1(char x[], int len1, char y[], int len2, int x1)
{
int i, j;
int ans = 0;
i = j = 0;
num = 0;
while (i < len2) {
while (-1 != j && y[i] != x[j]) j = next1[j];
i++; j++;
if(j >= len1) {
j = next1[j];
updata(i - len1+1 + x1, 1);
}
}
return;
}
int T, n;
char s[Max_N];
char t[15];
char s2[15];
char q[5];
int id;
int l, r;
int main()
{
scanf("%d", &T);
while (T--) {
memset(tree, 0, sizeof(tree));
scanf("%d", &n);
scanf("%s", s);
scanf("%s", t);
int len1 = strlen(s);
int len2 = strlen(t);
init(len1);
kmp_pre(t, len2, next1);
KMP_Count(t, len2, s, len1);
//cout << "ss" << endl;
for (int i = 0; i < n; i++) {
scanf("%s", q);
//cout << "ss" << endl;
if (q[0] == 'Q') {
scanf("%d%d", &l, &r);
printf("%d\n", query(1, 1, len4, l, r) - query(1, 1, len4, r - len2 + 2, r));
}
else {
scanf("%d%s", &id, q);
s[id-1] = q[0];
int l1 = max(1, id-len2);
int r1 = min(len1, id + len2);
int len3 = 0;
for (int j = l1-1; j <= r1-1; j++) {
s2[len3++] = s[j];
updata(j+1,0);
}
KMP_Count1(t, len2, s2, len3, l1-1);
}
cout << s << endl;
for (int i = 1; i <= len1; i++)
cout << query(1, 1, len4, i, i) << endl;
//cout << s << endl;
}
}
return 0;
}