题意:给定一个只包含A,T,C,G的字符串,有如下两种操作
1)修改一个点的字母
2)给定一个字符串e (strlen(e) <=10),生成一个由e重复组成的新串,eee...,问 L,R 区间中有几个字母跟这个新的字符串对应。
思路: 对每个字母建立10 * 10个树状数组(前面的10表示e的长度,后面表示mod e的长度后的值),表示区间中膜len(e) 结果为 k = (0...len(e)-1)的个数。
查询的话,对于给定的e 查询对应len(e)的树状数组
比如给定 e 为 ATC L = 2,R = 4
对于A 我们 查询长度为3的A的树状数组,
因为从L = 2开始,所以改为查询mod 3 == 1的总和
后面的T和C也一样。
可能说的不太清楚,,具体请见代码。
#include<bits/stdc++.h>
using namespace std;
#define _____ ios::sync_with_stdio(false); cin.tie(0);
#define ull unsigned long long
#define ll long long
#define lson l,mid,id<<1
#define rson mid+1,r,id<<1|1
typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
typedef pair<double, double>pdd;
const double eps = 1e-6;
const int MAXN = 100005;
const int MAXM = 5005;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
const double FINF = 10000000;
const ll MOD = 1000000007;
const double PI = acos(-1.0);
#define typev int // type of res
typev ar[4][11][10][MAXN]; // index: 1 ~ N
int lowb(int t) { return t & (-t) ; }
void add(int i,int pos,int ty,int f) {
for (; i < MAXN; i += lowb(i)) {
for (int k = 1; k <= 10; ++k) {
ar[ty][k][pos%k][i] += f;
}
}
}
typev sum(int i,int pos,int ty,int len)
{
typev s = 0;
for ( ; i > 0; s += ar[ty][len][pos][i], i -= lowb(i));
return s;
}
typev query(int x, int y,int pos,int ty,int len) {
return sum(y, pos, ty, len) - sum(x - 1, pos, ty, len);
}
int Ha[100];
int main()
{
Ha['A'] = 0, Ha['T'] = 1, Ha['G'] = 2, Ha['C'] = 3;
string s;
cin >> s;
for (int i = 0; i < s.size(); ++i) {
add(i + 1, i, Ha[s[i]], 1);
}
char ch[111];
int q,a,b,c; scanf("%d", &q);
while (q--) {
scanf("%d", &a);
if (a == 1) {
scanf("%d %s", &b, ch);
add(b, b - 1, Ha[s[b - 1]], -1);
add(b, b - 1, Ha[ch[0]], 1);
s[b - 1] = ch[0];
}
else
{
scanf("%d %d %s", &b, &c, ch);
int len = strlen(ch);
int ans = 0;
for (int i = 0; i < len; ++i) {
ans += query(b, c, (i + b - 1) % len, Ha[ch[i]], len);
}
printf("%d\n", ans);
}
}
}