WJX博客

学习笔记——Hash

前言

字符串\(Hash\)是将复杂的信息映射到一个简单的值域内,并使每一个字符串尽量均匀分布在其中,几乎不产生冲突(尽量让两个不同值不被映射成相同的值)的一种方法。

因为\(Hash\)更注重对其方法的理解,所以笔者就简单讲一下其思路,不会太过详细的讲解。

\(Hash\)的基本过程

我们采用进制的思想,把该字符串转化为某进制下的一个数并存储起来,之后就可以\(O(1)\)查询和匹配该字符串及其子串。

我们先来看模板题:

题意简述:给定\(N\)个字符串,求有多少个不同的字符串。

思路:都说是\(Hash\)的板子了,当然要用\(Hash\)了。我们可以用\(Hash\)将字符串映射为\(base\)进制的数,记录每一个字符串的值,再判断有多少个不同的值即可。

#include <iostream>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define il inline
#define ll long long
#define int long long
#define ull unsigned long long
#define re register
#define gc getchar
using namespace std;
//------------------------初始程序-------------------------- 
il int read(){
	re int x=0;re bool f=0;re char ch=gc();
	while(!isdigit(ch)){f|=ch=='-';ch=gc();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
	return f?-x:x;
}

il int max(int a,int b){
	return a>b?a:b;
}

il int min(int a,int b){
	return a<b?a:b;
}


//------------------------初始程序-------------------------- 

const int N=1e4+10,MOD=1e9+7;
ull base=131,a[N];//用unsigned long long 让它自然溢出
//a[i]记录第i个字符串的Hash值
char opt[N];//记录输入的字符串
int n,ans=1;//ans从1开始是因为第一个数一定跟其他数是不相同的

il ull hashe(int len) {
	ull res=0;//记录base进制下该字符串的值
	for(re int i=1;i<=len;++i) {
		res=(res*base+opt[i]+1)%MOD;
      	//生成该值,相当于把之前的值左移一位再加上该字符串第i位所代表的值  
      	//这里一定要注意加1,防止当前位值为0,降低与其他值冲突的可能 
	}
	return res;
}


signed main()
{
	n=read();
	for(re int i=1;i<=n;++i) {
		scanf("%s",opt+1);
		int len=strlen(opt+1);
		a[i]=hashe(len);
	}	
	sort(a+1,a+n+1);//把该值从小到大排序
	for(re int i=1;i<n;++i) 
		if(a[i]!=a[i+1]) ++ans;//如果相邻两个数不相等,答案加一
	printf("%lld\n",ans);
	return 0;
}

P3370 【模板】字符串哈希(Hash+Trie树的题解)(我的Hash代码)

P2957 [USACO09OCT]Barn Echoes G(求前缀后缀最长相等长度)(Hash题解)(我的Hash代码)

P7469 [NOI Online 2021 提高组] 积木小赛(民间数据)(题解)(我的代码)

本题有一堆正解,但\(Hash\)可能是其中最好想的(奈何考场没想到),像之前所说,我们可以用\(Hash\)来求\(t\)的任意子串,然后用一个二维数组(设为\(pos[i][j]\))记录第\(i\)位之后的第一个出现\(j\)字符的下标,\(O(n^2)\)暴力枚举\(t\)的每一个子串,将子串的\(Hash\)值记录,最后去重即可。

P5043 【模板】树同构([BJOI2015]树的同构)(题解)(我的代码)

本题要求我们将\(Hash\)运用到树上,对于树上的每一个节点,我们都可以求出以该节点为根节点的整棵树的\(Hash\)值,再在之前求出的\(Hash\)值中找到相同的输出即可。

以下为树同构另一道经典题(博主可能没时间做了,先咕着):

P4323 [JSOI2016]独特的树叶

posted @ 2021-08-05 15:52  WJX3078  阅读(40)  评论(0)    收藏  举报