字符串关键字的散列映射[平方探测法]

本文解析了如何使用移位法和素数散列,将大写英文字母组成的字符串通过特定算法映射到长度为P的散列表中,遇到冲突时采用平方探测法解决。实例演示了如何处理字符串'HELLOANNKZOELOLI',并介绍了关键知识点如字符映射、散列计算和平方探测法的应用。
摘要由CSDN通过智能技术生成

L . 案例5-1.4:字符串关键字的散列映射 [ 问题 9295 ] [ 讨论 ]
Description
给定一系列由大写英文字母组成的字符串关键字和素数 $P$ ,用移位法定义的散列函数$H (Key)$ 将关键字 $Key$ 中的最后3个字符映射为整数,每个字符占5位;再用除留余数法将整数映射到长度为$P$ 的散列表中。例如将字符串AZDEG插入长度为1009的散列表中,我们首先将26个大写英文字母顺序映射到整数0~25;再通过移位将其映射为3×32²+4×32+6=3206;然后根据表长得到3206,即是该字符串的散列映射位置。

发生冲突时请用平方探测法解决。

Input
输入第一行首先给出两个正整数$N$ ($\le 500$)和$P$ ($\ge 2N$ 的最小素数),分别为待插入的关键字总数、以及散列表的长度。第二行给出$N$ 个字符串关键字,每个长度不超过8位,其间以空格分隔。

Output
在一行内输出每个字符串关键字在散列表中的位置。数字间以空格分隔,但行末尾不得有多余空格。

Samples
Input 
4 11
HELLO ANNK ZOE LOLI
Output
3 10 4 0

Source
浙大版《数据结构学习与实验指导(第2版)》

单纯的介绍两个坑吧:
平方探测法应该是 pos±i*i进行探测,并不是单纯的+操作(除非题目有要求)
切记新的地址是 newpos = 原来的地址(即输入的地址或者题目要求所求的“首次”地址) ± d^2,而不是oldpos += d^2!!!(即老地址单纯加),整个寻址过程,递增的只有平方间隔d !!!
注意字符串长度可能小于3
judge数组的+1操作,避免sum%p==0 导致后期judge[str]==0,无法判重

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7;
int hash[N];
map<int,int>vis;
map<string,int>judge;
int main(){
	int n,p;
	cin>>n>>p;
	for(int i=1;i<=n;i++){
		string str;
		cin>>str;
		int sum=0;
		if(!judge[str]){
			for(int j=str.size()-1,e=1;j>=0&&e<=1*32*32;j--,e*=32) um+=(str[j]-'A')*e;
			int temp=sum;
			int pos=1;
            int opr=1;
			while(vis[sum%p]){
				sum=(temp+pos*pos*opr+p)%p;//这里要排除负数地址情况,否则不会过
                opr*=-1;
				if(opr>0) pos++;
			}
            judge[str]=sum%p+1;	//+1操作避免sum%p==0 导致后期judge[str]==0,无法判重
			vis[sum%p]=1;
		}
		cout<<judge[str]-1<<" ";//对应的-1操作
	}
	
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值