题目链接
很难的一道题吧,算是挺难了,就是想到挺复杂,作为我这么个Ju蒻来说。
题目给你一串字符串,是初始的字符串,然后告诉你一系列操作,问你:
(一)、改变点Xi上的字符;
(二)、查询【l,r】区间上的对应与新给的字符串匹配的个数是几个?例如“ACGTCGA”我们待查的是这个完整区间上的“AG”,那么“AG”会变成“AGAGAGA”与上述对应的点的个数就是3,第一位与最后两位。
思路:我们发现一点,就是待查询的区间长度很短,不超过10,那么我们是不是可以从中挖掘出什么来,既然最大长度为10,我们不如先做些预处理,知道原字符串的样子,我们通过其来初始化一下,就是看作每个分块。
怎么看作小分块?我们从1~10的大小拆分按序全体字符串,这个的目的是在于区分长度,然后,去看对应字符串字符又是不同的,怎么处理?可以再开个空间,反正就是4个字符,多开4倍还是够的,接下来的问题就是一一对应,怎么样做到一一对应?我们既然已经对字符串的待判长度做了预处理,不妨在想个办法判断出其在拆分出的字符串中应当存在的位子,我们从0~len-1来排位子就是只需要将字符所在位子去%此时的对应长度,就可以得到它应当存在的区间。
那么树状数组的开法就应当是这样的:C[在长度为len的条件下排在第几个][预处理长度len][元素符号][存在原数组中的第pos位]。那么,我们就可以建立树状数组了。
细节上别忘了,每次树状数组更新后记得也要改变原字符串中对应位子的元素符号。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 100005;
//const ull Hash1=1e9+7, Hash2=1e9+9;
//const char fu[5] = { ' ', 'A' , 'T', 'G', 'C' };
const int re_fu[26] = { 1, 0, 4, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 }; //fu[]-'A',在其中代表Z(对应符号所在的数位)
char s[maxN], ques[15];
int N, Q, flag, l, r, len;
int C[11][11][5][maxN];
void update(int x, int y, int z, int pos, int val) //x为数长、y为我们将其放在第几个、z是对应的数位置,pos是我们存入的位子,val是放一个(或者删除一个)
{
while(pos<maxN)
{
C[x][y][z][pos] += val;
pos += lowbit(pos);
}
}
int query(int x, int y, int z, int pos) //x为将其视为第几个,y是查询数的长度,z是待查询的数,pos是对应前缀
{
int res=0;
while(pos)
{
res += C[x][y][z][pos];
pos -= lowbit(pos);
}
return res;
}
int main()
{
while(scanf("%s", s+1)!=EOF)
{
memset(C, 0, sizeof(C));
N = (int)strlen(s+1);
for(int i=1; i<=N; i++)
{
for(int j=1; j<=10; j++)
{
update(i%j, j, re_fu[s[i]-'A'], i, 1);
}
}
scanf("%d", &Q);
while(Q--)
{
scanf("%d", &flag);
if(flag == 1)
{
scanf("%d", &l);
scanf("%s", ques);
for(int i=1; i<=10; i++)
{
update(l%i, i, re_fu[s[l]-'A'], l, -1);
update(l%i, i, re_fu[ques[0]-'A'], l, 1);
}
s[l] = ques[0];
}
else
{
int ans = 0;
scanf("%d%d", &l, &r);
scanf("%s", ques);
len = (int)strlen(ques);
for(int i=0; i<len; i++)
{
ans += query((l+i)%len, len, re_fu[ques[i]-'A'], r) - query( (l+i)%len, len, re_fu[ques[i]-'A'], l-1);
}
printf("%d\n", ans);
}
}
}
return 0;
}