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

哈希表

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

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

冲突处理:

  • 开放寻址法
  • 拉链法

拉链法

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

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;
}
相关推荐
淡海水36 分钟前
13-04-面试-源码级深度追问链
数据结构·unity·面试·c#·游戏引擎·源码·il2cpp
Logic1011 小时前
C语言/数据结构位运算题解:异或XOR找出时尚聚会中的“独特颜色“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
2401_839080544 小时前
C++常见八股
数据结构·c++·算法
暮雨封夕5 小时前
跳表(Skip List)详解:原理、实现、使用场景与实际应用
数据结构
miller-tsunami5 小时前
排序的相关知识点
数据结构·排序算法
Logic1019 小时前
C语言/数据结构滑动窗口题解:替换k个字符后的最长连续相同字符子串(LeetCode 424)
c语言·数据结构·字符串·滑动窗口·时间复杂度·频率统计·算法题
程序员阿鹏10 小时前
简单介绍一下软引用
java·开发语言·jvm·数据结构·后端
爱奥尼欧12 小时前
【C++】map、set 的底层是什么?红黑树五条性质、插入旋转到模拟实现
开发语言·数据结构·c++
黄金龙PLUS12 小时前
5个800比特大状态置换算法的设计与分析
算法·网络安全·密码学·哈希算法·同态加密
动词ing12 小时前
【题目练习】动态规划+背包问题
数据结构·目标检测