Solution 1 Bitset
每次匹配一段,可以看成,依次考虑每个位置,匹配的位置对应的起点取交集。例如:
大概就这个意思。
bitset的count似乎很慢,可以用__builtin_popcount来数中间的位数,然后暴力数两端的位数会快很多。感觉手写倍增法数位数最快。但有人说前面那个内联函数比手写的$O(\log \log n)$的速度要快。
Code
1 /** 2 * Codeforces 3 * Problem#914F 4 * Accepted 5 * Time: 2760ms 6 * Memory: 4300k 7 */ 8 #include <bits/stdc++.h> 9 using namespace std; 10 typedef bool boolean; 11 12 const int N = 1e5 + 5, alpha = 26; 13 14 int n, m; 15 char str[N], buf[N]; 16 bitset<N> ch[alpha], ans; 17 18 inline void init() { 19 scanf("%s", str + 1); 20 n = strlen(str + 1); 21 for (int i = 1; i <= n; i++) 22 ch[str[i] - 'a'][i] = 1; 23 scanf("%d", &m); 24 } 25 26 inline void solve() { 27 int opt, x, y, len; 28 while (m--) { 29 scanf("%d%d", &opt, &x); 30 if (opt == 1) { 31 scanf("%s", buf); 32 ch[str[x] - 'a'][x] = 0, ch[buf[0] - 'a'][x] = 1; 33 str[x] = buf[0]; 34 } else { 35 scanf("%d%s", &y, buf + 1); 36 len = strlen(buf + 1); 37 if (y - x + 1 < len) { 38 puts("0"); 39 continue; 40 } 41 ans.set(); 42 for (int i = 1; i <= len; i++) 43 ans &= (ch[buf[i] - 'a'] >> (i - 1)); 44 // for (int i = 1; i <= n; i++) 45 // cerr << ans[i] << " "; 46 // cerr << endl; 47 // for (int i = 1; i <= n; i++) 48 // cerr << (ans >> (x - 1))[i]; 49 // cerr << endl; 50 int res = (ans >> x).count() - (ans >> (y - len + 2)).count(); 51 printf("%d\n", res); 52 } 53 } 54 } 55 56 int main() { 57 init(); 58 solve(); 59 return 0; 60 }