Codeforces Round #423 (Div. 2) E. DNA Evolution(树状数组)

本文介绍了一种针对特定字符串问题的有效解决方案,通过使用树状数组来优化字符串匹配过程中的查询与更新操作。该方法适用于只有四种字符('A', 'T', 'G', 'C')的情况,并能高效处理多种操作,如修改指定位置的字符以及查询特定模式与原字符串间的匹配字符数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

给你一个只包含'A', 'T', 'G', 'C'的字符串,q次操作,有两种操作:

1 x ch : 将x位置改成ch

2 l r e:e为一个长度不超过10的字符串,问eeeee....与字符串的子串[l, r]有多少个匹配的字符(先将e的开头和l对齐)


思路:

一共就4种字符,可以分别考虑每个字符,e长度最大才10,可以分别考虑不同长度的e。

假设e长为len, 那么i , i+len ,i+len*2, i+len*3.....一定是去对应e的相同位置,pos%len相同可以归为一组,一共最多10个位置,所以可以开

10*10*4的树状数组,tree[x][y][z]记录的是e长度为y的对应置为x的字符为z的数量。


代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int tree[12][12][5][maxn], id[256];
char str[maxn], tmp[15];

int lowbit(int x)
{
    return x&(-x);
}

void update(int x, int y, int z, int pos, int val)
{
    while(pos < maxn)
    {
        tree[x][y][z][pos] += val;
        pos += lowbit(pos);
    }
}

int query(int x, int y, int z, int pos)
{
    int sum = 0;
    while(pos)
    {
        sum += tree[x][y][z][pos];
        pos -= lowbit(pos);
    }
    return sum;
}

int main(void)
{
    id['A'] = 0, id['T'] = 1, id['G'] = 2, id['C'] = 3;
    while(cin >> str)
    {
        memset(tree, 0, sizeof(tree));
        int len = strlen(str);
        for(int i = 1; i <= len; i++)
            for(int j = 1; j <= 10; j++)
                update(i%j, j, id[str[i-1]], i, 1);
        int q;
        scanf("%d", &q);
        while(q--)
        {
            int cmd, x, y;
            char ch;
            scanf("%d%d", &cmd, &x);
            if(cmd == 1)
            {
                scanf(" %c", &ch);
                for(int j = 1; j <= 10; j++)
                {
                    update(x%j, j, id[ch], x, 1);
                    update(x%j, j, id[str[x-1]], x, -1);
                }
                str[x-1] = ch;
            }
            else
            {
                scanf("%d %s", &y, tmp);
                int len = strlen(tmp);
                int ans = 0;
                for(int i = 1; i <= len; i++)
                    ans += query((x+i-1)%len, len, id[tmp[i-1]], y)-query((x+i-1)%len, len, id[tmp[i-1]], x-1);
                printf("%d\n", ans);
            }
        }
    }
    return 0;
}
/*
ATGCATGC
4
2 1 8 ATGC
2 2 6 TTT
1 4 T
2 2 6 TA

8
2
4
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值