题意:给你一个串k,进行两个操作:
“1 a b”:把a位置的字母换成b
“2 l r s”:求l到r有多少个字母和s匹配,匹配的条件是这样:从l开始无限循环s形成一个串ss,然后匹配ss和指定区间的匹配个数
分析:我们对于字符“A, T, G, C”存在的位置分别设为1,否则为0,这样我们可以开4*10*10个树状数组来对Q次操作进行动态更新,代码如下。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+100;
int c[4][11][11][maxn];
int len[maxn];
string s;
map<char, int>mp;
int lowbit(int x){
return x&(-x);
}
void update(int x, int n, int m, int v){
for(int k = 1; k <= 10; k++){
int g = x%k;
for(int j = x; j <= n; j+=lowbit(j)){
c[m][k][g][j]+=v;
}
}
}
int getsum(int x, int m, int k, int g){
int sum = 0;
for(int i = x; i > 0; i=i-lowbit(i)){
sum += c[m][k][g][i];
}
return sum;
}
int main(){
mp['A'] = 0;
mp['T'] = 1;
mp['G'] = 2;
mp['C'] = 3;
int q;
cin>>s;
int l = s.length();
s = " "+s;
for(int i = 1; i <= l; i++) update(i, l, mp[s[i]], 1);
cin>>q;
while(q--){
int op, x, ix, rx;
char u; string e;
scanf("%d", &op);
if(op == 1){
scanf("%d %c", &x,&u);
int m1 = mp[u];
int m2 = mp[s[x]];
update(x, l, m1, 1);
update(x, l, m2, -1);
s[x] = u;
}else{
scanf("%d%d", &ix, &rx); cin>>e;
int k = e.length();
int ans = 0;
for(int i = 0; i < k; i++){
int m = mp[e[i]];
ans += getsum(rx, m, k, (i+ix)%k) - getsum(ix-1, m, k, (i+ix)%k);
}
printf("%d\n", ans);
}
}
// cout<<s<<endl;
return 0;
}