当前位置: 首页 > news >正文

【数据结构】哈希表算法总结

知识概览(哈希表)

  • 哈希表可以将一些值域较大的数映射到较小的空间内,通常用x mod 质数的方式进行映射。为什么用质数呢?这样的质数还要离2的整数幂尽量远。这可以从数学上证明,这样冲突最小。
  • 取余还是会出现冲突情况。怎么解决冲突呢,有两种方式:开放寻址法和拉链法。
  • 算法题中哈希表的题目可能会有添加、查找操作,删除操作较少,删除用逻辑删除,即用一个bool数组来标识出哪些数已经被删除了。

例题展示

题目链接

https://www.acwing.com/problem/content/842/

代码(拉链法)

#include <iostream>
#include <cstring>using namespace std;const int N = 100010;int h[N], e[N], ne[N], idx;void insert(int x)
{int k = (x % N + N) % N;e[idx] = x;ne[idx] = h[k];h[k] = idx++;
}bool query(int x)
{int k = (x % N + N) % N;for (int i = h[k]; 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 (query(x)) puts("Yes");else puts("No");}}return 0;
}

代码(开放寻址法)

#include <iostream>
#include <cstring>using namespace std;const int N = 200003, null = 0x3f3f3f3f;  // 数组长度设置为题目数据范围的2~3倍且是质数int h[N];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) puts("Yes");else puts("No");}}return 0;
}

知识概览(字符串哈希)

  • 字符串哈希也称为字符串前缀哈希法,它先预处理出所有前缀的哈希值。
  • 主要思想是用一个P进制的角度把一个字符串看成一个数字。例如一个字符串"ABCD",假设A为1,B为2,C为3,D为4,则其哈希值为\left ( 1 \times P^3 + 2 \times P^2 + 3 \times P^1 + 4 \times P^0 \right )\mod Q,其中P可以取131或13331,Q可以取2^{64},这些是经验值,99.99%的情况下不会出现冲突,不解决冲突。
  • 字符串哈希用来快速判断两个字符串是不是相等。KMP算法可以求循环节,除此之外,KMP算法不如字符串哈希,字符串哈希确实简单直接。

例题展示

题目链接

https://www.acwing.com/problem/content/843/

题解

不用考虑取余,溢出相当于取余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);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)) puts("Yes");else puts("No");}return 0;
}

参考资料

  1. AcWing算法基础课
http://www.lryc.cn/news/262961.html

相关文章:

  • 微信小程序单图上传和多图上传
  • github入门基础操作
  • Android Studio(3.6.2版本)安装 java2smali 插件,java2smali 插件的使用方法简述
  • vscode使用remote ssh到server上 - Node进程吃满CPU
  • 如何在Go中使用日期和时间
  • 2023_Spark_实验二十九:Flume配置KafkaSink
  • Koa.js 入门手册:洋葱模型插件机制详解以及常用中间件
  • 零信任 SASE 办公安全解决方案:提升企业网络安全与灵活性
  • 【提示工程】Chain-of-Thought Prompting Elicits Reasoning in Large Language Models
  • AWS解决方案架构师学习与备考
  • 如何搭建企业管理系统Odoo并远程访问管理界面【内网穿透】
  • 【Git】git常用问题汇总
  • 2024免费mac苹果电脑系统电脑管家CleanMyMac X
  • ElasticSearch详细搭建以及常见错误high disk watermark [ES系列] - 第497篇
  • ADB:获取坐标
  • 关于“Python”的核心知识点整理大全27
  • 实验三 MapReduce编程
  • element组件库的日期选择器如何限制?
  • QSqlQueryModel
  • docker-compose介绍和用法
  • Mac下ERROR: Cannot connect to the Docker daemon
  • 本地项目添加到gitlab命令操作
  • t-io 程序执行后,jvm不退出的原因
  • Vue3使用Three.js导入gltf模型并解决模型为黑色的问题
  • 说一下 jvm 有哪些垃圾回收算法?
  • 【23真题】一共10道题,押题卷5道!
  • JS的浅拷贝和深拷贝
  • 天软特色因子看板 (2023.12 第12期)
  • 【Logback技术专题】「入门到精通系列教程」深入探索Logback日志框架的原理分析和开发实战技术指南(上篇)
  • vue3+element Plus 清空el-tree复选框选中项