关于初学Hash

最简单的Hash思想就是建立一个大于等于值域的数组进行统计和映射

主要操作:

1.计算Hash函数的值
2.定位到对应链表中依次遍历、比较

一般是大数%一个较大的质数,如算阶上给的公式:

H(x)=(x%P)+1;

这是最常用的,P就是一个很大的质数,因此我们平时要记着几个大的质数,如99991,131,13331,有些数据量比较大且不考高精的题让%的大多也是质数。
记得有道题好像%的不是质数所以输出0就能40分,但据说河南没人想出来这么做

还有:

1.直接定址法:H(x)=x或H(x)=a*x+b
2.数字分析法:取关键字的若干位组成哈希地址
3.平方取中法:关键字平方后取中间几位
4.折叠法:将关键数字分割成位数的及部分,取叠加和作为哈希地址
5.伪随机数法:先生成随机数序列r[N],然后H(x)=r[x]


Hash主要是把复杂的信息映射到一个容易被维护的值域里,而值域变小就很容易造成冲突。
所以Hash很重要的一个步骤就是得解决冲突。
鄙人主要在伟人的书2中看到以下两种做法:

1.拉链法

相同的地址关键字值均链入对应列表中

2.线性探测法

为冲突的关键字找到新的哈希地址


再来看道板子题

题目描述

很久很久以前,森林里住着一群兔子。有一天,兔子们想要研究自己的 DNA 序列。我们首先选取一个好长好长的 DNA 序列(小兔子是外星生物,DNA 序列可能包含 26 个小写英文字母),然后我们每次选择两个区间,询问如果用两个区间里的 DNA 序列分别生产出来两只兔子,这两个兔子是否一模一样。注意两个兔子一模一样只可能是他们的 DNA 序列一模一样

输入和输出

Input

第一行一个 DNA 字符串 S。 接下来一个数字 m,表示 m 次询问。 接下来 m 行,每行四个数字 l1, r1, l2, r2,分别表示此次询问的两个区间,注意字符串的位置从1开始编号。 其中 1 ≤ length(S), m ≤ 1000000

Output

对于每次询问,输出一行表示结果。如果两只兔子完全相同输出 Yes,否则输出 No(注意大小写)

样例

Sample Input

aabbaabb
3
1 3 5 7
1 3 6 8
1 2 1 2

Sample Output

Yes
No
Yes

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
char s[N];
unsigned long long rabbita,rabbitb,n,t,f[N],p[N],l1,r1,l2,r2;
int main()
{
    
    
	scanf("%s",s+1);
	n=strlen(s+1),p[0]=1;
	cin>>t;
	for(int i=1;i<=n;i++)
	{
    
    
		f[i]=f[i-1]*131+(s[i]-'a'+1);
		p[i]=p[i-1]*131;
	}
	for(int i=1;i<=t;i++)
	{
    
    
		scanf("%lld%lld%lld%lld",&l1,&r1,&l2,&r2);
		rabbita=f[r1]-f[l1-1]*p[r1-l1+1];
		rabbitb=f[r2]-f[l2-1]*p[r2-l2+1];
		if(rabbita==rabbitb)	puts("Yes");
		else	puts("No");
	}
	return 0;
}

这个用无符号long long记录,爆掉就爆掉吧,反正无符号时没有负数,爆了之后还是整数
但是这个数据量大得感人,用cout会超时,得用puts,而puts还自带换行很方便。

猜你喜欢

转载自blog.csdn.net/ydsrwex/article/details/113578590
今日推荐