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

哈希表

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

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

冲突处理:

  • 开放寻址法
  • 拉链法

拉链法

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

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;
}
相关推荐
刘马想放假2 天前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
北域码匠3 天前
冒泡排序太慢?鸡尾酒排序双向优化,原生 C# 零第三方库完整代码
数据结构·排序算法·泛型·c# 算法·鸡尾酒排序·原生 c# 开发·冒泡排序优化·嵌入式算法
Darling噜啦啦10 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
小小工匠11 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
玖玥拾11 天前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
Qres82111 天前
算法复键——树状数组
数据结构·算法
牛油果子哥q11 天前
并查集(DSU)超精讲,路径压缩、按秩合并、万能模板、连通性判定、最小生成树与刷题实战全解
数据结构·c++·最小生成树·并查集
凌波粒11 天前
LeetCode--491.递增子序列(回溯算法)
数据结构·算法·leetcode
WL学习笔记11 天前
单项不带头不循环链表
数据结构·链表
小糯米60111 天前
JS 数组
数据结构·算法·排序算法