首页 > 其他分享 >Hash哈希学习笔记

Hash哈希学习笔记

时间:2024-08-31 08:57:11浏览次数:10  
标签:modp hash 哈希 int 笔记 long ull Hash

概念:通过一个hash函数建立值与存储地址的关系

原则:

  • 开小数组+冲突解决
  • 冲突越少,用时越少;可通过调整余数或优质的hash算法尽量使hash值分散,减少碰撞

hash算法的构成:

hash函数的初始化

构造hash函数:

典型的函数包括除余法 H ( k ) = ( k ) m o d p H(k)=(k)modp H(k)=(k)modp、elfhash等等

冲突解决方法:

(常用技术)线性探测再散列技术:当 ( k ) m o d p (k)modp (k)modp下标对应有元素时,依次探测 ( k + i ) m o d p (k+i)modp (k+i)modp下标位置直至数组为空,再将元素放入。

再开数组辅助定位:

在存储后,使用hash函数定位某个元素时,不仅需要一个数组确定某个下标位置是否存在元素,当某个位置有元素时还需要一个数组存储该位置的原本元素方便精确校验是否为该元素。

拓展hash:

  • 字符串哈希
    使用elfhash算法bkdrHash算法尽可能的减少存储时的,其冲突,其他操作与经典hash无区别
    bkdrhash
    h a s h ( s ) = ( ∑ i = 1 l s [ i ] × b a s e l − i ) m o d M hash(s)=(\sum^l_{i=1} s[i]\times base^{l-i})modM hash(s)=(∑i=1l​s[i]×basel−i)modM或者
    h a s h ( s ) = ( ∑ i = 1 l s [ i ] × b a s e i − 1 ) m o d M hash(s)=(\sum^l_{i=1} s[i]\times base^{i-1})modM hash(s)=(∑i=1l​s[i]×basei−1)modM
  1. 自然溢出法
    利用C++中的unsigned long long 数据类型声明哈希值,就相当于使用大数的自然溢出为哈希值模 2 64 − 1 2^{64}-1 264−1这个数。
#include<bits/stdc++.h>
#define maxn 100000
#define INF 0x3f3f3f3f
#define ull unsigned long long
using namespace std;
int N,base=233,cnt=1;
char s[2000];
ull h[maxn];
ull hashhit(char *str)
{
    ull res=0;
    int len=strlen(str);
    for(int i=0;i<len;i++)
    res=(res*base+(ull)str[i]);//自然溢出
    return res&0x7fffffff;//相当于将位数控制在int最大位数内
}
int main()
{
    scanf("%d",&N);
    for(int i=0;i<N;i++)
    {
        scanf("%s",s);
        h[i]=hashhit(s);
    }
    sort(h,h+N);
    for(int i=0;i<N-1;i++)
    if(h[i]!=h[i+1])
    cnt++;
    printf("%d",cnt);
    system("pause");
}
  1. 单哈希
    即使用一个mod值和base值计算哈希值
  2. 双哈希
    即使用两个mod值和base值确定两个哈希值,从而确定一个字符串。代码:
#include<bits/stdc++.h>//自然溢出双哈希,bkrd算法
#define maxn 100000
#define INF 0x3f3f3f3f
#define ull unsigned long long
using namespace std;
int N,base1=233,cnt=1,base2=2333;
char s[2000];
struct dhash{
    ull x;
    ull y;
}h[maxn];
ull hashhit1(char *str)
{
    ull res=0;
    int len=strlen(str);
    for(int i=0;i<len;i++)
    res=(res*base1+(ull)str[i]);//自然溢出
    return res&0x7fffffff;//相当于将位数控制在int最大位数内
}
ull hashhit2(char *str)
{
    ull res=0;
    int len=strlen(str);
    for(int i=0;i<len;i++)
    res=(res*base2+(ull)str[i]);//自然溢出
    return res&0x7fffffff;//相当于将位数控制在int最大位数内
}
int cmp(dhash a,dhash b)
{
    if(a.x!=b.x)
    return a.x<b.x;
    else
    return a.y<b.y;
}
int main()
{
    scanf("%d",&N);
    for(int i=0;i<N;i++)
    {
        scanf("%s",s);
        h[i].x=hashhit1(s);
        h[i].y=hashhit2(s);
    }
    sort(h,h+N,cmp);
    for(int i=0;i<N-1;i++)
    if(h[i].x!=h[i+1].x||h[i].y!=h[i+1].y)
    cnt++;
    printf("%d",cnt);
    system("pause");
}
  • 全排列哈希(康托展开)
    介绍:
    康托展开是一种能建立全排列与自然数之间的双射关系的方法;具体算法如下:
    自然数为X, X = a n ( n − 1 ) ! + a n − 1 ( n − 2 ) ! + . . . . + a 1 0 ! X=a_n(n-1)!+a_{n-1}(n-2)!+....+a_10! X=an​(n−1)!+an−1​(n−2)!+....+a1​0!其中系数 a i a_i ai​为全排列中所有种类的数字剔除已经出现的数字的集合,集合内小于第i位数的数字的个数。如54123,从左到右依次计算系数a,此时集合内有{1,2,3,4,5}这些数字,小于5的数字有4个,则 a 5 = 4 a_5=4 a5​=4,同时剔除已经出现的数字5,集合内还剩{1,2,3,4},下一个数字为4,以此类推 a 4 = 3 , a 3 = 0 , a 2 = 0 , a 1 = 0 a_4=3,a_3=0,a_2=0,a_1=0 a4​=3,a3​=0,a2​=0,a1​=0,综上该数对应114因此,将全排列通过康托展开映射到hash表是hash算法中效率最高的选择。

标签:modp,hash,哈希,int,笔记,long,ull,Hash
From: https://blog.csdn.net/2301_79974919/article/details/141712452

相关文章

  • 一文说透 String 的 HashCode
    首先需要明确版本,不同版本的实现是不同的。JDK1.8以前底层的实现是char[]。publicinthashCode(){inth=hash;if(h==0&&value.length>0){charval[]=value;for(inti=0;i<value.length;i++){h=31*......
  • 读书笔记(9)《冯唐成事心法 》
    序言这本书的框架分四部分:知己、知人、知世、知智慧。知道自己、知道团队、知道如何处世、知道智慧怎么增长。前三个方面,是从小处着手,最后一个方面,是从大处着眼,可以在更高的层次上,做更大的事。知己——比如,逆境来了怎么办,如何分清自己的欲望和志向,如何学会与自己好好相处,等等。......
  • Redis基础知识学习笔记(一)
    文章目录Redis简介Redis简介REmoteDIctionaryServer(Redis)是一个由SalvatoreSanfilippo写的key-value存储系统,是跨平台的非关系型数据库,其是一个开源的使用ANSIC语言编写、遵守BSD协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)......
  • HashMap 的长度为什么是2的幂次方?
    一、均匀分布哈希值当HashMap的长度是2的幂次方时,通过hashCode()计算出哈希值后,再与(length-1)进行与操作(例如index=hashCode()&(table.length-1)),可以使得哈希值更加均匀地分布在数组的下标范围内。假设哈希值是均匀分布的,那么与操作可以充分利用哈希值的各个位,......
  • CMake构建学习笔记12-libzip库的构建
    如果要更方便地压缩/解压缩文件或者文件夹,除了使用基于zlib的minizip库,更推荐使用另一个基于zlib的库libzip,个人认为其接口设计更科学一点,文档也更丰富一点。不过libzip库本身的构建倒是没什么特别的,关键指令如下所示:#配置CMakecmake..-G"$Generator"-Ax64`-DCMAK......
  • 笔记——莫队
    蓝月の笔记——莫队篇简介莫队算法是由莫涛提出的算法。在莫涛提出莫队算法之前,莫队算法已经在Codeforces的高手圈里小范围流传,但是莫涛是第一个对莫队算法进行详细归纳总结的人。莫涛提出莫队算法时,只分析了普通莫队算法,但是经过OIer和ACMer的集体智慧改造,莫队有了多种扩......
  • 【Qt笔记】QListView控件详解
     目录引言一、QListView基本概念1.1定义与功能1.2架构原理二、QListView基本使用2.1创建QListView和Model2.2设置QListView的属性2.3处理用户交互三、QListView高级技巧3.1自定义委托3.2使用QStandardItemModel3.3实现拖放功能四、QListView......
  • Yolov5入门介绍(官网文档学习笔记)
    一、yolov5是什么yolov5是yolo的第五次迭代,旨在提供高速、高精度的目标检测模型官方文档:ComprehensiveGuidetoUltralyticsYOLOv5-UltralyticsYOLODocs二、yolov5的优点1、高速、高精度 (例如R-CNN目标检测有两部:先生成候选框再分类)2、基于pytorch搭建,使用于各......
  • 哈希
    树状数组是个好东西,写起来也相对好看。但是操作比较局限,区间修改就掉回\(O(nlogn)\),那还不如\(O(n)\)。线段树完美的解决问题。线段树,也可以理解的一堆线段组成的树。大致如上,有一线段\([l,r]\)当\(l\ner\)可化为\([l,mid]\),\([mid+1,r]\)PS:\(mid=(l+r......
  • 插入类型 DP 学习笔记
    插入类型DP形式多为nnn个元素无法重复使用,需要给定一个排列,满足一定条件或是求有多少个排列满足一定条件。nnn一般在100∼5×103100\sim5\times10^3100∼5×103左右。满足一些函数图像,类似于波浪函数,且答案与每个波浪和波浪的顶点有关(函数的xxx坐标为下标,yy......