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

哈希表

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

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

冲突处理:

  • 开放寻址法
  • 拉链法

拉链法

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

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;
}
相关推荐
pearlthriving3 小时前
list的介绍
数据结构·list·1024程序员节
给大佬递杯卡布奇诺5 小时前
FFmpeg 基本数据结构 AVInputFormat 分析
数据结构·c++·ffmpeg·音视频
给大佬递杯卡布奇诺5 小时前
FFmpeg 基本数据结构 AVCodecContext分析
数据结构·c++·ffmpeg·音视频
budingxiaomoli7 小时前
算法--滑动窗口(一)
数据结构·算法
想唱rap9 小时前
C++ list 类的使用
c语言·开发语言·数据结构·c++·笔记·算法·list
仰泳的熊猫11 小时前
LeetCode:773. 滑动谜题
数据结构·c++·算法·leetcode
huangql52012 小时前
JavaScript数据结构实战指南:从业务场景到性能优化
javascript·数据结构·性能优化
hope_wisdom14 小时前
C/C++数据结构之用链表实现栈
c语言·数据结构·c++·链表·
大肘子咒你14 小时前
数字狂潮来袭
数据结构·c++·1024程序员节