哈希
哈希表
哈希表是将值域比较大但数量比较少的数快速插入与查找的数据结构
哈希表有两种写法,一种是拉链法,一种是开放寻址法
拉链法
拉链法的核心思想是将一个大数取模,如 x mod N
具体做法就是将模完的这个数映射到与它相同的数组下标,并从这一位拉一个单链表
如图:
例题代码如下:
#include <iostream> #include <cstring> using namespace std; const int N = 100003; int h[N], e[N], ne[N], idx; // 与单链表的定义类似 void insert(int x) // 插入一个元素 { int t = (x % N + N) % N; // 输入的数有可能是负数,需要加一个N再模N e[idx] = x; ne[idx] = h[t]; h[t] = idx; idx ++ ; } bool find(int x) // 寻找x { int t = (x % N + N) % N; for (int i = h[t]; i != -1; i = ne[i]) if (e[i] == x) return true; return false; } int main() { int n; scanf("%d", &n); memset(h, -1, sizeof h); while (n -- ) { char op[2]; int x; scanf("%s%d", op, &x); if (*op == 'I') insert(x); else { if (find(x)) printf("Yes"); else printf("No"); } } return 0; }
算法题中一般没有删除操作,如果有,那就将每一个数打上一个标记
开放寻址法
开放寻址法和我们蹲厕所类似,如果经过hash函数之后这个位有元素我们就看下个位置有没有元素
因此数组就需要开的大一点,一般开数据范围的两到三倍
当然也 N 最好也取到一个质数
将拉链法的例题用开放寻址法写代码如下
#include <iostream> #include <cstring> using namespace std; const int N = 200003; int h[N], null = 0x3f3f3f3f; // null 这个数比10的九次方大 int find(int x) { int k = (x % N + N) % N; while (h[k] != null && h[k] != x) { k ++ ; if (k == N) k = 0; } return k; } int main() { int n; scanf("%d", &n); memset(h, 0x3f, sizeof h); while (n -- ) { char op[2]; int x; scanf("%s%d", op, &x); int k = find(x); if (*op == 'I') h[k] = x; else { if (h[k] != null) printf("Yes\n"); else printf("No\n"); } } return 0; }
字符串哈希
字符串哈希可以实现快速比较两个区间中的元素是否相同
原理是将一个字符串转换成一个p进制数
这里的模 Q 代码中不需要写,因为我们可以用 unsigned long long
以下为字符串哈希的几个注意事项:
- 字符不能映射成0,否则可能有多个字符串同时映射成0
- 假设我们的RP足够好,不存在冲突的情况,但我们有一个经验值,P = 131 或 13331(取这两个数基本不会发生冲突),Q = 2^64
例题代码:
#include <iostream> using namespace std; typedef unsigned long long ULL; const int N = 100010, P = 131; int n, m; char str[N]; ULL h[N], p[N]; ULL get(int l, int r) { return h[r] - h[l - 1] * p[r - l + 1]; } int main() { scanf("%d%d%s", &n, &m, str + 1); // 从1开始更方便 p[0] = 1; for (int i = 1; i <= n; i ++ ) { p[i] = p[i - 1] * P; h[i] = h[i - 1] * P + str[i]; } while (m -- ) { int l1, r1, l2, r2; scanf("%d%d%d%d", &l1, &r1, &l2, &r2); if (get(l1, r1) == get(l2, r2)) printf("Yes\n"); else printf("No\n"); } return 0; }
本文作者:张詠然
本文链接:https://www.cnblogs.com/zyrddd/p/16515785.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步