[数据结构]哈希表、字符串哈希

哈希表

哈希表: 通过键快速查找到对应的值的数据结构。

实现方法: 为了方便实现, 使用模运算实现, 通常除数使用质数, 从而减少哈希冲突的概率

冲突处理:

  • 开放寻址法
  • 拉链法

拉链法

对于哈希到相同槽位的不同关键字,用一个链表将它们串联起来

cpp 复制代码
#include <iostream>
#include <cstring> 
using namespace std;

const int N = 100003; 
int a[N], h[N], ne[N], idx = 1;
//a是存储数据的节点
//h是头节点
//ne是节点的下一个节点的下标
//全部值都共用一个数组,也就是得出下标不同的数据共用一个数组但使用不同的位置

void insert(int x)
{
	int k = (x % N + N) % N; 
	ne[idx] = h[k];
	a[idx] = x;
	h[k] = idx++;
}

bool query(int x)
{
	int k = (x % N + N) % N; 
	for (int i = h[k]; i != 0; i = ne[i]) 
		if (a[i] == x)
			return true;
	return false;
}

int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		char chr;
		int x;
		cin >> chr >> x;
		if (chr == 'I')
			insert(x);
		else
		{
			if (query(x))
				cout << "Yes\n";
			else
				cout << "No\n";
		}
	}
	return 0;
}

开放寻址法

空间通常要开大2~3倍

如果下标已经有数据就找下标+1的位置存储数据

cpp 复制代码
#include <iostream>
#include <cstring> //(注:原文缺少)
using namespace std;

const int N = 300007, null = 0x3f3f3f3f;
int a[N];

int find(int x)
{
	int k = (x % N + N) % N; 
	while (a[k] != null && a[k] != x)
	{
		k++;
		if (k == N)k = 0;
	}
	return k;
}

int main()
{
	int n;
	cin >> n;
	memset(a, 0x3f, sizeof(a));
	while (n--)
	{
		char chr;
		int x;
		cin >> chr >> x;
		int k = find(x);
		if (chr == 'I')
			a[k] = x;
		else
		{
			if (a[k] == x)cout << "Yes\n";
			else cout << "No\n";
		}
	}
	return 0;
}

字符串哈希方式

字符串前缀哈希法 把字符串看成是一个p进制的数, ( A B C D ) p ( m o d Q ) ( A B C D )_p \pmod Q (ABCD)p(modQ),

  • 取值 : 通常取值 P=131或13331, Q= 2 64 2^{64} 264, 用unsigned long long 当溢出的时候就相当于取模。

作用: 方便求任意区间内的哈希值 -> 快速判断两个字符串是否相同

  • [l,r] -> h ( r ) − h ( l − 1 ) ⋅ p r − l + 1 h(r)-h(l-1) \cdot p^{r-l+1} h(r)−h(l−1)⋅pr−l+1

841. 字符串哈希 - AcWing题库

cpp 复制代码
#include <iostream>
using namespace std;

typedef unsigned long long ULL;

const int N = 100010, P = 131;
char c[N];
ULL h[N], p[N];

ULL get(int l, int r)
{
	return h[r] - h[l - 1] * p[r - l + 1];
}

int main()
{
	int n, m;
	cin >> n >> m >> c + 1;
	p[0] = 1;
	for (int i = 1; i <= n; i++)
	{
		p[i] = p[i - 1] * P;
		h[i] = h[i - 1] * P + c[i];
	}

	while (m--)
	{
		int l1, r1, l2, r2;
		cin >> l1 >> r1 >> l2 >> r2;
		if (get(l1, r1) == get(l2, r2))
			cout << "Yes\n";
		else
			cout << "No\n";
	}
	return 0;
}
相关推荐
未若君雅裁几秒前
LeetCode 51 - N皇后问题 详解笔记
java·数据结构·笔记·算法·leetcode·剪枝
小王C语言25 分钟前
优先算法---双指针和滑动窗口
数据结构
夜晚中的人海30 分钟前
【C++】哈希表算法习题
c++·算法·散列表
大袁同学4 小时前
【哈希hash】:程序的“魔法索引”,实现数据瞬移
数据结构·c++·算法·哈希算法·散列表
@卞6 小时前
ST 表相关练习题
数据结构·c++·算法
Ace_31750887766 小时前
拼多多关键字搜索接口逆向:从 WebSocket 实时推送解析到商品数据结构化重建
数据结构·websocket·网络协议
天选之女wow7 小时前
【Hard——Day4】25.K 个一组翻转链表
数据结构·算法·leetcode·链表
曾经的三心草7 小时前
Java数据结构-List-栈-队列-二叉树-堆
java·数据结构·list
拾忆,想起10 小时前
Dubbo负载均衡全解析:五种策略详解与实战指南
java·运维·微服务·架构·负载均衡·dubbo·哈希算法
一直在努力的小宁10 小时前
《代码随想录-精华内容提取》07 二叉树
数据结构·算法·链表·面试