- B1: 前缀和与差分
- B2: 快速组合
- B3: 二分查找
- B4: 高精度加法
- B4: 高精度除法
- B4: 高精度乘法
- B4: 高精度减法
- D1: 单调栈
- D2: 单调队列
- D3: Spare Table
- D4: 字典树
- D5: 并查集
- D6: 树状数组-限定区间计数
- D6: 树状数组-单点更新区间求和
- D7: 线段树-基础
- G1: 二分图-判定
- G2: 二分图-最大匹配
- G3: Astar k短路 on matrix
- G4: 拓扑排序
- G5: 连通无环无向图的重心
- G6: MST-Kruskal
- G7: MST-Prim
- G8: ShortestPath-BellmanFord
- G9: ShortestPath-Dijkstra
- G9: ShortestPath-Dijkstra Heap OPT
- G10: ShortestPath-SPFA
- G11: ShortestPath-Floyd
- M1: 快速幂与龟速乘
- M2: 欧几里得-最大公约数
- M2: EX欧几里得-翡蜀定理
- M2: EX欧几里得-线性同余方程
- M2: EX欧几里得-乘法逆元
- M3: 费马小定理-乘法逆元
- M4: 分解质因数
- M4: 分解质因数-欧拉函数
- M4: 分解质因数-多数乘积约数计数
- M4: 分解质因数-多数乘积约数求和
- M5: 欧拉筛
- M5: 欧拉筛-质数筛
- M6: 埃氏筛-质数筛
- M7: Stein算法-最大公约数
- M8: 矩阵乘法与快速幂
- O1: 快速排序
- O2: 并归排序
- S1: KMP
- S2: 字符串哈希
class string_hash {
string s;
ullong ar[maxn + 1] {};
ullong bin[maxn+1] {1ULL};
const ullong base = 131ULL;
public:
explicit string_hash(string &str):s(move(str)) {
for (int i = 0; i < s.length(); i++) {
ar[i + 1] = ar[i] * base + s[i];
bin[i+1] = bin[i] * base;
}
}
ullong hash(const int l, const int r) {
return ar[r] - ar[l] * bin[r - l];
}
};
Notes
-
base的经验取值为131、13331 - 类型使用
unsigned long long, 对2^64取模,溢出即取模 -
l,r类似于begin(),end(),hash(l, r)返回子串[l, r)的哈希值
字符串哈希的运用
运用哈希方法解决字符串模式匹配问题
class strhash {
ullong ar[maxn + 1] {};
ullong bin[maxn + 1] {1ULL};
const ullong base = 131ULL;
const int len;
public:
explicit strhash(string &tar): len(tar.length()) {
for (int i = 0; i < len; i++) {
ar[i + 1] = ar[i] * base + tar[i];
bin[i + 1] = bin[i] * base;
}
}
int solve(string &s) {
ullong val = 0ULL;
int cnt = 0;
for (ullong i : s) (val *= base) += i;
for (int l = 0, r = s.length(); r <= len; ++l, ++r)
if (ar[r] - ar[l] * bin[s.length()] == val) ++cnt;
return cnt;
}
};
Notes
-
bin[0]必须初始化为1 - 对于题目的具体要求不同, 适当修改
count_patterns函数即可 - 如果有必要, 哈希值相同的情况下应进一步判断是否真正相等