事情的起因来自这个:
前情提要: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; }
 
 
   |