事情的起因来自这个:
前情提要:bitset 和 __builtin 函数 | Legendgod’s Blog
$\text{Ha宝: bitset 还可以加速字符串匹配}$。
$\text{legendgod: /se/se}$。
如果手动实现一个 $\tt bitset$ 会怎么搞,肯定是通过一个 $\tt int$ 压起来,之后如果范围内的就查表,如果范围外就直接暴力跳,这样复杂度是有一个 $\frac{1}{w}$ 的常数,同理其一位只需要一个 $\tt Byte$。
关于字符串匹配我们考虑对于文本串 $S$,找出每个字符 $c$ 出现的所有位置,存在 $bt_c$ 中。
对于一个串 $T$ 考虑对于其每个位置都与 $S$ 进行一次暴力匹配,不妨设其长度为 $m$。
考虑记录一个答案 $\tt bitset$,$ans$。其中 $ans_i$ 表示位置 $i$ 能否成为答案。
对于位置 $i$ 的元素 $T_i$ 我们考虑让 ans &= bt[T[i]] << (m - i - 1)
,可以发现这个东西本质就是对于每一位都进行一次验证。
串是从 $0$ 开始的。
最终 $ans$ 在合法区间内的 $1$ 就是答案了。
Substrings in a String - 洛谷
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| #include <bits/stdc++.h> using namespace std; namespace Legendgod { namespace Read {
#ifdef Fread const int Siz = (1 << 21) + 5; char *iS, *iT, buf[Siz]; #define gc() ( iS == iT ? (iT = (iS = buf) + fread(buf, 1, Siz, stdin), iS == iT ? EOF : *iS ++) : *iS ++ ) #define getchar gc #endif template <typename T> void r1(T &x) { x = 0; char c(getchar()); int f(1); for(; !isdigit(c); c = getchar()) if(c == '-') f = -1; for(; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48); x *= f; } template <typename T, typename...Args> void r1(T &x, Args&...arg) { r1(x), r1(arg...); } #undef getchar }
using namespace Read;
const int maxn = 1e5 + 5; int n, m; bitset<maxn> bt[26]; bitset<maxn> ans; char S[maxn], t[maxn];
signed main() { int i, j; scanf("%s", S); n = strlen(S); for(i = 0; i < n; ++ i) bt[S[i] - 'a'].set(i); int Q; r1(Q); while(Q --) { int opt, l, r; r1(opt); if(opt == 1) { r1(l), scanf("%s", t), -- l; bt[S[l] - 'a'].reset(l), bt[(S[l] = t[0]) - 'a'].set(l); } else { r1(l, r), scanf("%s", t); -- l, -- r, m = strlen(t); ans.set(); for(i = 0; i < m; ++ i) ans &= (bt[t[i] - 'a'] << (m - i - 1)); int res = (ans >> (l + m - 1)).count() - (ans >> (r + 1)).count(); printf("%d\n", max(res, 0)); } }
return 0; }
}
signed main() { return Legendgod::main(), 0; }
|
Frequency of String - 洛谷
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| #include <bits/stdc++.h> using namespace std; namespace Legendgod { namespace Read {
#ifdef Fread const int Siz = (1 << 21) + 5; char *iS, *iT, buf[Siz]; #define gc() ( iS == iT ? (iT = (iS = buf) + fread(buf, 1, Siz, stdin), iS == iT ? EOF : *iS ++) : *iS ++ ) #define getchar gc #endif template <typename T> void r1(T &x) { x = 0; char c(getchar()); int f(1); for(; !isdigit(c); c = getchar()) if(c == '-') f = -1; for(; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48); x *= f; } template <typename T, typename...Args> void r1(T &x, Args&...arg) { r1(x), r1(arg...); } #undef getchar }
using namespace Read;
const int maxn = 2e5 + 5; int n, m; char S[maxn], T[maxn]; bitset<maxn> bt[26], ans; int p[maxn], tot(0);
signed main() { int i, j; scanf("%s", S); n = strlen(S); for(i = 0; i < n; ++ i) bt[S[i] - 'a'].set(i); int Q; r1(Q); while(Q --) { int k; r1(k), scanf("%s", T); m = strlen(T); ans.set(); for(i = 0; i < m; ++ i) ans &= (bt[T[i] - 'a'] << (m - i - 1)); tot = 0; for(i = ans._Find_first(); i != ans.size(); i = ans._Find_next(i)) if(i >= m - 1) p[++ tot] = i; int ans(2e5); if(tot < k) { puts("-1"); continue; } for(i = k; i <= tot; ++ i) ans = min(ans, p[i] - p[i - k + 1]); printf("%d\n", ans + m); } return 0; }
}
signed main() { return Legendgod::main(), 0; }
|