首页 > 其他分享 >哈希

哈希

时间:2024-08-03 20:08:09浏览次数:9  
标签:pwr int mid overline maxn 哈希

前置芝士:字符串常用方法

推荐文章:花的哈希基础介绍

其中讲了无错哈希和多重哈希,但没讲如何 \(O(1)\) 求出子串哈希值。

这里把字符串 \(s\) 看成 \(p\) 进制数,使用自然溢出法。

技巧:子串哈希

我们可以用 \(O(n)\) 的时间预处理出所有前缀的 hash 值,然后可以 \(O(1)\) 求出子串哈希值。

具体地,令 \(f_{1…i}\) 表示 \(s_{1…i}\) 的哈希值,则有:

\(f_i=f_{i-1}\times p+s_i\)

就是向右挪一位再在最低位加一个数。

如果要求出 \([l,r]\) 的哈希值,可以这样做:

\(hash(l,r)=f_r-f_{l-1}\times p^{r-l+1}\)

就是把 \(s_{1…l-1}\) 挪到最高位再减掉。

例如:

\(\mathtt{abcdef}\)

欲求 \(hash(3,6)\) 即 \(\mathtt{cdef}\) 的哈希值(简称为 \(\overline{cdef}\))。

我们预处理后知道 \(f_2\) 和 \(f_6\)。

也就是知道了 \(\overline{abcdef}\) 和 \(\overline{ab}\)。

但是这两个不能直接相减,要把 \(\overline{ab}\) 挪到数位对齐。

于是我们把 \(\overline{ab}\) 变成 \(\overline{ab0000}\),也就是把 \(f_2\) 乘上了
\(p^4\)。

相减:

\[\;\;\quad\;\overline{abcdef} \]

\[-\quad\;\overline{ab0000} \]

\[=\quad\overline{00cdef} \]

省略 \(0\) 就变成了 \(\overline{cdef}\)。


总结

预处理:

\(f_i=f_{i-1}\times p+s_i\)(这里的 \(s_i\) 最好定义为减 'a' 加 1)

求 \([l,r]\) 的哈希值:

\(hash(l,r)=f_r-f_{l-1}\times p^{r-l+1}\)(最好提前处理出 \(p\) 的次幂)

例 1:138. 兔子与兔子

子串哈希裸题。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5,p=131;
typedef unsigned long long ull;
string s;
ull f[maxn],pwr[maxn];
void init()
{
	pwr[0]=1;
	for(int i=1;i<s.size();i++)pwr[i]=pwr[i-1]*p;
	for(int i=1;i<s.size();i++)f[i]=f[i-1]*p+(s[i]-'a'+1);
}
ull ask(int l,int r){return f[r]-f[l-1]*pwr[r-l+1];}
int main()
{
	cin>>s;s.insert(0,"0");
	init();
	int T;
	cin>>T;
	for(int i=1;i<=T;i++)
	{
		int l1,r1,l2,r2;
		cin>>l1>>r1>>l2>>r2;
		if(ask(l1,r1)==ask(l2,r2))
			cout<<"Yes"<<endl;
		else
			cout<<"No"<<endl;
	}
	return 0;
}

例 2:139. 回文子串的最大长度

将字符串正着和倒着 hash 一遍,如果一个串正着和倒着的 hash 值相等则这个串是回文串。枚举每个节点以及每个分割点为回文中心,二分即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5,p=131;
typedef unsigned long long ull;
string s;
ull f[maxn],g[maxn],pwr[maxn];
int ans;
void init()
{
	memset(f,0,sizeof(f));
	memset(g,0,sizeof(g));
	memset(pwr,0,sizeof(pwr));
	ans=0;
	pwr[0]=1;
	for(int i=1;i<s.size();i++)pwr[i]=pwr[i-1]*p;
	for(int i=1;i<s.size();i++)f[i]=f[i-1]*p+(s[i]-'a'+1);
	for(int i=s.size()-1;i>=1;i--)g[i]=g[i+1]*p+(s[i]-'a'+1);
}
ull ask1(int l,int r){return f[r]-f[l-1]*pwr[r-l+1];}
ull ask2(int l,int r){return g[l]-g[r+1]*pwr[r-l+1];}
bool check1(int cntr,int x)
{
	int l=cntr-x,r=cntr+x;
	if(ask1(l,r)==ask2(l,r))
		return 1;
	return 0;
}
bool check2(int cntr,int x)
{
	int l=cntr-x+1,r=cntr+x;
	if(ask1(l,r)==ask2(l,r))
		return 1;
	return 0;
}
int main()
{
	for(int c=1;;c++)
	{
		cin>>s;
		if(s=="END")
			break;
		s.insert(0,"0");
		init();
		for(int i=1;i<s.size();i++)
		{
			int l=0,r=min(i-1,(int)s.size()-i-1),res=0;
			while(l<=r)
			{
				int mid=(l+r)>>1;
				if(check1(i,mid))
				{
					res=mid;
					l=mid+1;
				}
				else
					r=mid-1;
			}
			ans=max(ans,1+2*res);
			l=0,r=min(i,(int)s.size()-i-1),res=0;
			while(l<=r)
			{
				int mid=(l+r)>>1;
				if(check2(i,mid))
				{
					res=mid;
					l=mid+1;
				}
				else
					r=mid-1;
			}
			ans=max(ans,2*res);
		}
		cout<<"Case "<<c<<": "<<ans<<endl;
	}
	return 0;
}

标签:pwr,int,mid,overline,maxn,哈希
From: https://www.cnblogs.com/tai-chi/p/18340976

相关文章

  • 【Rust光年纪】提升数据安全性与完整性:Rust语言哈希算法库深度对比
    深入探索Rust中的哈希算法库:安装配置与API解析前言在现代软件开发中,数据的安全性和完整性是至关重要的。哈希算法作为一种常见的数据加密和校验手段,在Rust语言中有着广泛的应用。本文将介绍几个用于Rust语言的常见哈希算法库,包括blake2、sha2、md5、crc32、xxhash以及siph......
  • HashMap是如何解决哈希冲突的?
    1.要了解Hash冲突,首先要先了解Hash算法和Hash表(1)Hash算法,就是把任意长度的输入,通过散列算法,变成固定长度的输出,这个输出结果是散列值.(2)Hash表又叫做“散列表”,它是通过key直接访问在内存存储位置的数据结构,在具体实现上,我们通过hash函数把key映射到表中的某......
  • # 代码随想录二刷(哈希表)
    代码随想录二刷(哈希表)三数之和思路反正对于我来说是真的难想出来。若这道题还是采用哈希表的思路去做,非常麻烦,并且还要考虑去重的操作。所以这道题其实用双指针,是更方便的。具体程序如下:classSolution:defthreeSum(self,nums:List[int])->List[List[int]]:......
  • P3501 [POI2010] ANT-Antisymmetry 反对称 题解(字符串哈希+二分)
    原题题意若一个由010101组成的字符串将000和......
  • 3.哈希表
    哈希表1.引入哈希表又称散列表,一种以「key-value」形式存储数据的数据结构。所谓以「key-value」形式存储数据,是指任意的键值key都唯一对应到内存中的某个位置。只需要输入查找的键值,就可以快速地找到其对应的value。可以把哈希表理解为一种高级的数组,这种数组的下标......
  • 哈希表——4.三数之和
    力扣题目链接给你一个包含n个整数的数组 nums,判断 nums 中是否存在三个元素a,b,c,使得 a+b+c=0?请你找出所有满足条件且不重复的三元组。注意: 答案中不可以包含重复的三元组。示例:输入:nums=[-1,0,1,2,-1,-4]输出:[[-1,0,1],[-1,-1,2]]由于题目中规定不可以......
  • [笔记]字符串哈希
    定义把一个字符串映射到一个整数的函数称作哈希函数,映射到的这个整数就是这个字符串的哈希值。需要注意的一点是,哈希是将大空间上的东西(字符串有无穷多个)映射到了小空间(一定范围内的整数),所以必定会存在冲突,即若干个不同的字符串映射到了相同的哈希值,我们将这种冲突称作“哈希碰......
  • LeetCode LCR 124.推理二叉树(哈希表 + 建树)
    某二叉树的先序遍历结果记录于整数数组 preorder,它的中序遍历结果记录于整数数组 inorder。请根据 preorder 和 inorder 的提示构造出这棵二叉树并返回其根节点。注意:preorder 和 inorder 中均不含重复数字。示例1:输入:preorder=[3,9,20,15,7],inorder=......
  • 自开发的哈希生成器(SHG)迎来 ULTRA 版本,内含新技术 SNF,详细介绍开发过程
     上链接:GitHub项目地址https://github.com/nitsc/Strong-Hash-Generator/tree/main/UltraCSDN上的介绍https://blog.csdn.net/zwa20110606/article/details/140708538**功能特点:****ULTRA版本**提供了以下功能:-使用了10层哈希算法: 1.SHA3-256   2.SHA3-5......
  • 最细哈希表相关的力扣题和讲解和Java、C++常用的数据结构(哈希法)来源于代码随想录,十分
    20240725一、什么时候适用什么样的结构。1.java中1.1HashSet:1.2TreeSet:1.3LinkedHashSet:1.4HashMap:1.5TreeMap:1.6LinkedHashMap:1.7总结2.c++中2.1std::unordered_set:2.2std::set:2.3std::multiset:2.4std::unordered_map:2.5std::map:2.6std::multimap:3代码......