hash问题

1.hash中的map函数

2.进制hash

hash是对一个串的单向加密过程。

<1>map函数

#include<map>//头文件

map<int, string> ID_Name;

int型数据变成string型数据,有点像加密的过程。

其他类型的转换也是一样的。

如int转int

map<int,int>ID_Name;

map有点像桶排,但是与map函数相比,桶排太垃圾了。
map可以看做一个集合,是数据结构,map的底层是散列表(hash),比桶排领域大很多
它Key所对应的Value可以是其他的容器,基本数据类型等。

map能处理的数据比较多种多样。

P1102 A-B 数对

P1102 A-B 数对 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题解:

1.对于这个题目我一开始先想到的就是桶排,但是后来对于负数的处理有点复杂就放弃了。

果断选了map。

2.找到这个值之后将它存在一个特定位置,然后再将这个值减去减数,最后将所有数的差值的数量加起来。

代码如下

#include<cstdio>
#include<cstring>
#include<map>
#include<iostream>
using namespace std;
int s[200009];
long long ans;
map<int,int>mapStudent;
int main()
{
	int n,c;
	scanf("%d%d",&n,&c);
	for(int m=0;m<n;m++)
	{
	scanf("%d",&s[m]);
	mapStudent[s[m]]++;//存入后 
	s[m]-=c;//找到本身值的差值 
	}
	for(int m=0;m<n;m++)
	ans+=mapStudent[s[m]];//差值数量相加 
	cout<<ans; 
	return 0;	
} 

P2580 于是他错误的点名开始了

P2580 于是他错误的点名开始了 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题解:

1.这个题目也可以用map,将string转换成int,存在一个特定位置。

2.判断一个名字是否出现一次或者不止一次,只要在名字出现一次将map数组中的值改成-1。

代码如下

#include<bits/stdc++.h>
using namespace std;
map<string,int>m;
string s;
int main()
{
	int n,t,i;
	cin>>n;
	for(i=0;i<n;i++)
	{
		cin>>s;
		m[s]=1;
	}
	cin>>t;
	for(i=0;i<t;i++)
	{
		cin>>s;
		if(m[s]==1)
		{
		printf("OK\n");
		m[s]=-1;
		}
		else if(m[s]==-1)
		printf("REPEAT\n");
		else
		printf("WRONG\n");
	}
	return 0;
}

<2>进制hash

进制哈希的核心便是给出一个固定进制k,将一个串的每一个元素看做一个进制位上的数字,所以这个串就可以看做一个k进制的数,那么这个数就是这个串的哈希值;则我们通过比对每个串的的哈希值,即可判断两个串是否相同。

ans=(ans*k+(long long int)s[i])%mod;

取模的意义是为了ans太大,防止溢出。

mod要取大一点!!!

P3370 【模板】字符串哈希

P3370 【模板】字符串哈希 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

1.这个是一个套进制hash的题,没有多余的要解释的地方。

2.再将所有数hash加密后,排序,判断一下左右的hash值是否相等。就可以判断有多少个不相等的字符串了。

代码如下

#include<bits/stdc++.h>
using namespace std;
long long int n,g[10009];
char s[1510];
long long int b=131;
long long int mod=212370440130137957ll;//mod的取值要大一点,最好是质数                                     
long long int ans;
int hah(char s[])
{
	int len=strlen(s);
	ans=0;
	for(int i=0;i<len;i++)
	{
		ans=(ans*b+(long long int)s[i])%mod;//取模是为了防止溢出 
	}
	return ans;
}
int main()
{
	scanf("%d",&n);
	int m,t;
	for(m=0;m<n;m++)
	{
		scanf("%s",s);
		g[m]=hah(s);
	}
	sort(g,g+n);
	t=1;
	for(m=0;m<n-1;m++)
	{
		if(g[m]!=g[m+1])
		t++;
	}
	cout<<t; 
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值