Hash算法个人理解

本文介绍了哈希算法在处理大规模数据和字符串比较中的应用。通过特定的哈希函数,将大数转化为便于处理的形式,并利用哈希表解决雪花识别问题,寻找可能相同的雪花对。同时展示了在字符串哈希中如何判断两个DNA序列是否相同,通过计算哈希值和区间对比来确定。
摘要由CSDN通过智能技术生成

Hash算法

H a s h Hash Hash算法,个人的理解是将若干个不方便表示的数(如数据过大等),通过一个特定的函数将其转化为方便表示的数,在此基础上进行操作。

详细概念如下:百度百科

比如,如果数据量过大,无法开桶进行统计(其实桶计数就是函数 y = x y=x y=x),那么可以将每一个数都 m o d mod mod一个质数( m o d mod mod质数的原因是减小冲突),用模得的数代表原数。
再比如,字符串 H a s h Hash Hash中,将每一个字符串进行 H a s h Hash Hash处理,就可以用一个数来代表一个字符串,通过这个数来对字符串进行操作、判断。
具体细节操作请自行学习

例题1

Snowflake Snow Snowflakes

时间限制:4s 空间限制:64MB

题目描述

您可能听说没有两个雪花是相似的。 你的任务是编写一个程序来确定这是否真的如此。 您的程序将读取有关雪花集合的信息,并搜索可能相同的一对。 每个雪花都有六个手臂。 对于每个雪花,您的程序将提供六个臂中每个臂的长度的测量。 任何具有相同长度相应臂的雪花都应该被程序标记为可能相同。

输入格式

第一行输入将包含一个整数n,0 n 100000,要遵循的雪花数量。 接下来是n行,每行描述一个雪花。 每个雪花将由包含六个整数的线(每个整数至少为0且小于10000000)描述,雪的长度为ake。 臂的长度将围绕雪花顺序给出(顺时针或逆时针),但它们可以从六个臂中的任何一个开始。 例如,相同的雪花可以描述为1 2 3 4 5 6或4 3 2 1 6 5。

输出格式

如果所有雪花都不同,您的程序应该打印消息: No two snowflakes are alike. 如果有一对可能相同的雪花,您的程序应该打印消息: Twin snowflakes found.

样例数据

input
2
output
1 2 3 4 5 6
4 3 2 1 6 5

代码如下:

#include<bits/stdc++.h>
using namespace std;
int n;
const int pri=99991;
int sum,mul;
bool flag;
int val;
int head[110000];
int nxt[110000];
int tot;
int snow[110000][6];
int gethash(int *a)
{
	sum=0;mul=1;
	for(int i=0;i<6;i++)
	{
		sum=(sum+a[i])%pri;
		mul=(long long)mul*a[i]%pri;
	}
	return (sum+mul)%pri;
}
bool equal(int *a,int *b)
{
	for(int i=0;i<6;i++)
	{
		for(int j=0;j<6;j++)
		{
			flag=1;
			for(int k=0;k<6;k++)
			{
				if(a[(i+k)%6]!=b[(j+k)%6]) 
				{
					flag=0;	
				}
			}
			if(flag==1)
			{
				return 1;
			}
			flag=1;
			for(int k=0;k<6;k++)
			{
				if(a[(i+k)%6]!=b[(j-k+6)%6])
				{
					flag=0;
				}
			}
			if(flag==1)
			{
				return 1;
			}
		}	
	}
	return 0;
}
bool check(int *a)
{
	val=gethash(a);
	for(int i=head[val];i;i=nxt[i])
	{
		if(equal(snow[i],a))
		{
			return 1;
		}
	}
	++tot;
	memcpy(snow[tot],a,6*sizeof(int));
	nxt[tot]=head[val];
	head[val]=tot;
	return 0;
}
void init()
{
	cin>>n;
}
int main()
{
	init();
	for(int i=1;i<=n;i++)
	{
		int a[10];
		for(int j=0;j<6;j++)
		{
			cin>>a[j];
		}
		if(check(a))
		{
			cout<<"Twin snowflakes found.";
			return 0;
		}
	}
	cout<<"No two snowflakes are alike.";
	return 0;
}

例题2(字符串 h a s h hash hash

兔子与兔子
题目描述

很久很久以前,森林里住着一群兔子。有一天,兔子们想要研究自己的 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(注意大小写)

样例数据

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

输出
Yes
No
Yes

代码如下:

#include<bits/stdc++.h>
using namespace std;
int qr()
{
	int x=0,flag=0;char ch=0;
	while(!isdigit(ch)) {flag|=ch=='-';ch=getchar();}
	while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return flag? -x:x;
}
string s;
int m;
unsigned long long f[1100000];
unsigned long long pri[1100000];
const int upri=13331;
int l1,r1,l2,r2;
char ch[1100000];
int len;
void init()
{
	getline(cin,s);
	len=s.size();
	for(int i=1;i<=len;i++)
	{
		ch[i]=s[i-1];
	}
}
void work()
{
	pri[0]=1;
	for(int i=1;i<=len;i++)
	{
		f[i]=f[i-1]*upri+(ch[i]-'a'+1);
		pri[i]=pri[i-1]*upri;
	}
}
void print()
{
	m=qr();
	for(int i=1;i<=m;i++)
	{
		l1=qr();r1=qr();l2=qr();r2=qr();
		int pp=f[r1]-f[l1-1]*pri[r1-l1+1];
		int qq=f[r2]-f[l2-1]*pri[r2-l2+1];
		if(pp==qq)
		{
			puts("Yes");
		}
		else puts("No");
	}
}
int main()
{
	init();
	work();
	print();
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值