【字符串】之关于初学哈希(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.线性探测法

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


再来看道板子题

题目描述

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

输入和输出

Input

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

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;
}

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

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值