Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) Problem E (Codeforces 828E) - 分块

Everyone knows that DNA strands consist of nucleotides. There are four types of nucleotides: "A", "T", "G", "C". A DNA strand is a sequence of nucleotides. Scientists decided to track evolution of a rare species, which DNA strand was string s initially.

Evolution of the species is described as a sequence of changes in the DNA. Every change is a change of some nucleotide, for example, the following change can happen in DNA strand "AAGC": the second nucleotide can change to "T" so that the resulting DNA strand is "ATGC".

Scientists know that some segments of the DNA strand can be affected by some unknown infections. They can represent an infection as a sequence of nucleotides. Scientists are interested if there are any changes caused by some infections. Thus they sometimes want to know the value of impact of some infection to some segment of the DNA. This value is computed as follows:

  • Let the infection be represented as a string e, and let scientists be interested in DNA strand segment starting from position l to position r, inclusive.
  • Prefix of the string eee... (i.e. the string that consists of infinitely many repeats of string e) is written under the string s from position lto position r, inclusive.
  • The value of impact is the number of positions where letter of string s coincided with the letter written under it.

Being a developer, Innokenty is interested in bioinformatics also, so the scientists asked him for help. Innokenty is busy preparing VK Cup, so he decided to delegate the problem to the competitors. Help the scientists!

Input

The first line contains the string s (1 ≤ |s| ≤ 105) that describes the initial DNA strand. It consists only of capital English letters "A", "T", "G" and "C".

The next line contains single integer q (1 ≤ q ≤ 105) — the number of events.

After that, q lines follow, each describes one event. Each of the lines has one of two formats:

  • 1 x c, where x is an integer (1 ≤ x ≤ |s|), and c is a letter "A", "T", "G" or "C", which means that there is a change in the DNA: the nucleotide at position x is now c.
  • 2 l r e, where lr are integers (1 ≤ l ≤ r ≤ |s|), and e is a string of letters "A", "T", "G" and "C" (1 ≤ |e| ≤ 10), which means that scientists are interested in the value of impact of infection e to the segment of DNA strand from position l to position r, inclusive.
Output

For each scientists' query (second type query) print a single integer in a new line — the value of impact of the infection on the DNA.

Examples
input
ATGCATGC
4
2 1 8 ATGC
2 2 6 TTT
1 4 T
2 2 6 TA
output
8
2
4
input
GAGTTGTTAA
6
2 3 4 TATGGTG
1 1 T
1 6 G
2 5 9 AGTAATA
1 10 G
2 2 6 TTGT
output
0
3
1
Note

Consider the first example. In the first query of second type all characters coincide, so the answer is 8. In the second query we compare string "TTTTT..." and the substring "TGCAT". There are two matches. In the third query, after the DNA change, we compare string "TATAT..."' with substring "TGTAT". There are 4 matches.


  我告诉我同学我用分块把这道题A掉了,我同学喷我为毛不去打比赛,我表示这场比赛A,B题好坑啊。。

  不多扯废话了。

  题目大意 给定一个字符串和一些操作。操作是修改字符串某个位置的字符,查询是给定一个比较短的字符串从这个字符串的a位置开始,一直到b位置,循环这个较短的字符串进行逐字节比较,输出匹配的字符数。

  不难想到用各种线段树,树状数组,然而为了简单粗暴,我选择了分块(显然树状数组做起来更简单)。

  根据常用套路,很容易得到每个块要记录下标模1到模10的余数为r,字符为c的出现次数。

  初始化块的时候暴力3重for去统计。修改时for模数,然后按意思修改一下就好了(注意字符串也要改)。

  查询时,先判断起始是否在同一块中,如果在,直接暴力for去算答案。否则就暴力for块两端的部分,中间暴力枚举块存储的数据,根据模查询字符串长度下的模数去统计(我也不好说清楚,是在不懂可以看代码,如果还不懂,就在评论区问一下吧)。

  总时间复杂度

Code

  1 /**
  2  * Codeforces
  3  * Problem#828E
  4  * Accepted
  5  * Time:1107ms
  6  * Memory:4104k
  7  */
  8 #include <iostream>
  9 #include <cstdio>
 10 #include <ctime>
 11 #include <cmath>
 12 #include <cctype>
 13 #include <cstring>
 14 #include <cstdlib>
 15 #include <fstream>
 16 #include <sstream>
 17 #include <algorithm>
 18 #include <map>
 19 #include <set>
 20 #include <stack>
 21 #include <queue>
 22 #include <vector>
 23 #include <stack>
 24 #ifndef WIN32
 25 #define Auto "%lld"
 26 #else
 27 #define Auto "%I64d"
 28 #endif
 29 using namespace std;
 30 typedef bool boolean;
 31 const signed int inf = (signed)((1u << 31) - 1);
 32 const signed long long llf = (signed long long)((1ull << 61) - 1);
 33 const double eps = 1e-6;
 34 const int binary_limit = 128;
 35 #define smin(a, b) a = min(a, b)
 36 #define smax(a, b) a = max(a, b)
 37 #define max3(a, b, c) max(a, max(b, c))
 38 #define min3(a, b, c) min(a, min(b, c))
 39 template<typename T>
 40 inline boolean readInteger(T& u){
 41     char x;
 42     int aFlag = 1;
 43     while(!isdigit((x = getchar())) && x != '-' && x != -1);
 44     if(x == -1) {
 45         ungetc(x, stdin);    
 46         return false;
 47     }
 48     if(x == '-'){
 49         x = getchar();
 50         aFlag = -1;
 51     }
 52     for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0');
 53     ungetc(x, stdin);
 54     u *= aFlag;
 55     return true;
 56 }
 57 
 58 int cti(char x) {
 59     if(x == 'A')    return 0;
 60     if(x == 'C')    return 1;
 61     if(x == 'G')    return 2;
 62     return 3;
 63 }
 64 
 65 typedef class Chunk {
 66     public:
 67         int id;
 68         int counter[11][11][4];        // moder, rest, character
 69         
 70         Chunk() {        };
 71         Chunk(int id):id(id) {
 72             memset(counter, 0, sizeof(counter));
 73         }
 74 }Chunk;
 75 
 76 int n, m;
 77 int cs, cc;
 78 char s[100005];
 79 vector<Chunk> lis;
 80 
 81 inline void init() {
 82     gets(s);
 83     readInteger(n);
 84     m = strlen(s);
 85     cs = (int)sqrt(m + 0.5);
 86 }
 87 
 88 inline int disposeWithBeginning(int a, char* buf, int len) {
 89     int sid = a / cs, ret = 0;
 90     for(int i = a; i < (sid + 1) * cs; i++) {
 91         if(s[i] == buf[(i - a) % len])
 92             ret++;
 93     }
 94     return ret;
 95 }
 96 
 97 inline int disposeWithEnding(int a, int b, char* buf, int len) {
 98     int eid = b / cs, ret = 0;
 99     for(int i = eid * cs; i <= b; i++) {
100         if(s[i] == buf[(i - a) % len])
101             ret++;
102     }
103     return ret;
104 }
105 
106 inline void init_chunks() {
107     for(cc = 0; cc * cs <= m; cc++) {
108         Chunk b(cc);
109         for(int mod = 1; mod <= 10; mod++) {
110             for(int rest = 0; rest < mod; rest++) {
111                 int start_pos = cc * cs - (cc * cs) % mod + rest;
112                 if(start_pos < cc * cs)    start_pos += mod;
113                 for(int i = start_pos; i < (cc + 1) * cs; i += mod)
114                     b.counter[mod][rest][cti(s[i])]++;
115             }
116         }
117         lis.push_back(b);
118     }
119 }
120 
121 inline void solve() {
122     int opt, a, b, len, res;
123     char buf[15];
124     while(n--) {
125         readInteger(opt);
126         readInteger(a);
127         a--;
128         if(opt == 1) {
129             scanf("%s", buf);
130             int bid = a / cs;
131             char bchar = s[a];
132             for(int mod = 1; mod <= 10; mod++) {
133                 b = a % mod;
134                 lis[bid].counter[mod][b][cti(buf[0])]++, lis[bid].counter[mod][b][cti(bchar)]--;
135             }
136             s[a] = buf[0];
137         } else {
138             res = 0;
139             readInteger(b);
140             b--;
141             scanf("%s", buf);
142             len = strlen(buf);
143             int sid = a / cs, eid = b / cs;
144             if(sid == eid) {
145                 for(int i = a; i <= b; i++) {
146                     if(s[i] == buf[(i - a) % len])
147                         res++;
148                 }
149             } else {
150                 for(int i = sid + 1; i < eid; i++) {
151                     int base = (i * cs - a) % len;
152                     int rbase = (i * cs) % len;
153                     for(int j = 0; j < len; j++) {
154                         res += lis[i].counter[len][(rbase + j) % len][cti(buf[(base + j) % len])];
155                     }
156                 }
157                 res += disposeWithBeginning(a, buf, len);
158                 res += disposeWithEnding(a, b, buf, len);
159             }
160             printf("%d\n", res);
161         }
162     }
163 }
164 
165 int main() {
166     init();
167     init_chunks();
168     solve();
169     return 0;
170 }
posted @ 2017-07-13 09:30  阿波罗2003  阅读(328)  评论(0编辑  收藏  举报