【Hash】字符串哈希
Hash 的核心思想在于,将输入映射到一个值域较小、可以方便比较的范围,典型的用法就是将资源紧张的设备中的不定长字符串转化为定长整数,以达到节省空间的目的
如:printf("This is a string.") => printf("0x12345678") // 理想哈希算法可将不同的字符串转化为唯一的整数
常用hash算法:
- 00 - RS 哈希函数
unsigned int RSHash(const char* str, unsigned int length)
{
unsigned int b = 378551;
unsigned int a = 63689;
unsigned int hash = 0;
unsigned int i = 0;
for (i = 0; i < length; ++str, ++i)
{
hash = hash * a + (*str);
a = a * b;
}
return hash;
}
- 01 - JS 哈希函数
unsigned int JSHash(const char* str, unsigned int length)
{
unsigned int hash = 1315423911;
unsigned int i = 0;
for (i = 0; i < length; ++str, ++i)
{
hash ^= ((hash << 5) + (*str) + (hash >> 2));
}
return hash;
}
- 02 - PJW 哈希函数
unsigned int PJWHash(const char* str, unsigned int length)
{
const unsigned int BitsInUnsignedInt = (unsigned int)(sizeof(unsigned int) * 8);
const unsigned int ThreeQuarters = (unsigned int)((BitsInUnsignedInt * 3) / 4);
const unsigned int OneEighth = (unsigned int)(BitsInUnsignedInt / 8);
const unsigned int HighBits = (unsigned int)(0xFFFFFFFF) << (BitsInUnsignedInt - OneEighth);
unsigned int hash = 0;
unsigned int test = 0;
unsigned int i = 0;
for (i = 0; i < length; ++str, ++i)
{
hash = (hash << OneEighth) + (*str);
if ((test = hash & HighBits) != 0)
{
hash = (( hash ^ (test >> ThreeQuarters)) & (~HighBits));
}
}
return hash;
}
- 03 - ELF哈希函数
unsigned int ELFHash(const char* str, unsigned int length)
{
unsigned int hash = 0;
unsigned int x = 0;
unsigned int i = 0;
for (i = 0; i < length; ++str, ++i)
{
hash = (hash << 4) + (*str);
if ((x = hash & 0xF0000000L) != 0)
{
hash ^= (x >> 24);
}
hash &= ~x;
}
return hash;
}
- 04 - BKDR 哈希函数
unsigned int BKDRHash(const char* str, unsigned int length)
{
unsigned int seed = 131; /* 31 131 1313 13131 131313 etc.. */
unsigned int hash = 0;
unsigned int i = 0;
for (i = 0; i < length; ++str, ++i)
{
hash = (hash * seed) + (*str);
}
return hash;
}
- 05 - SDBM哈希函数
unsigned int SDBMHash(const char* str, unsigned int length)
{
unsigned int hash = 0;
unsigned int i = 0;
for (i = 0; i < length; ++str, ++i)
{
hash = (*str) + (hash << 6) + (hash << 16) - hash;
}
return hash;
}
- 06 - DJB哈希函数
unsigned int DJBHash(const char* str, unsigned int length)
{
unsigned int hash = 5381;
unsigned int i = 0;
for (i = 0; i < length; ++str, ++i)
{
hash = ((hash << 5) + hash) + (*str);
}
return hash;
}
- 07 - DEK哈希函数
unsigned int DEKHash(const char* str, unsigned int length)
{
unsigned int hash = len;
unsigned int i = 0;
for (i = 0; i < length; ++str, ++i)
{
hash = ((hash << 5) ^ (hash >> 27)) ^ (*str);
}
return hash;
}
- 08 - AP 哈希函数
unsigned int APHash(const char* str, unsigned int length)
{
unsigned int hash = 0xAAAAAAAA;
unsigned int i = 0;
for (i = 0; i < length; ++str, ++i)
{
hash ^= ((i & 1) == 0) ? ( (hash << 7) ^ (*str) * (hash >> 3)) :
(~((hash << 11) + ((*str) ^ (hash >> 5))));
}
return hash;
}
各hash算法冲突率测评
| Hash函数 | 数据1 | 数据2 | 数据3 | 数据4 | 数据1得分 | 数据2得分 | 数据3得分 | 数据4得分 | 平均分 |
| BKDRHash | 2 | 0 | 4774 | 481 | 96.55 | 100 | 90.95 | 82.05 | 92.64 |
| APHash | 2 | 3 | 4754 | 493 | 96.55 | 88.46 | 100 | 51.28 | 86.28 |
| DJBHash | 2 | 2 | 4975 | 474 | 96.55 | 92.31 | 0 | 100 | 83.43 |
| JSHash | 1 | 4 | 4761 | 506 | 100 | 84.62 | 96.83 | 17.95 | 81.94 |
| RSHash | 1 | 0 | 4861 | 505 | 100 | 100 | 51.58 | 20.51 | 75.96 |
| SDBMHash | 3 | 2 | 4849 | 504 | 93.1 | 92.31 | 57.01 | 23.08 | 72.41 |
| PJWHash | 30 | 26 | 4878 | 513 | 0 | 0 | 43.89 | 0 | 21.95 |
| ELFHash | 30 | 26 | 4878 | 513 | 0 | 0 | 43.89 | 0 | 21.95 |
数据1:为100000个字母和数字组成的随机串哈希冲突个数
数据2:为100000个有意义的英文句子哈希冲突个数
数据3:为数据1的哈希值与 1000003(大素数)求模后存储到线性表中冲突的个数
数据4:为数据1的哈希值与10000019(更大素数)求模后存储到线性表中冲突的个数。
经过比较,得出以上平均得分。平均数为平方平均数。可以发现,BKDRHash无论是在实际效果还是编码实现中,效果都是最突出的。APHash也是较为优秀的算法。DJBHash,JSHash,RSHash与SDBMHash各有千秋。
PJWHash与ELFHash效果最差,但得分相似,其算法本质是相似的。
参考:
http://www.partow.net/programming/hashfunctions/
https://www.cnblogs.com/uvsjoh/archive/2012/03/27/2420120.html
【Hash】字符串哈希的更多相关文章
- HASH 字符串哈希 映射转化
哈希HASH的本质思想类似于映射.离散化. 哈希,通过给不同字符赋不同的值.并且钦定一个进制K和模数,从而实现一个字符串到一个模意义下的K进制数上. 它的主要目的是判重,用于$DFS$.$BFS$判重 ...
- 详解HASH(字符串哈希)
HASH意为(散列),是OI的常用算法. 我们常用哈希的原因是,hash可以快速(一般来说是O(段长))的求出一个子段的hash值,然后就可以快速的判断两个串是否相同. 今天先讲string类的has ...
- 数据结构作业——hash(字符串哈希)
Hash Description 给定长度为 n ( n<=1000000)的字符串,字符串仅由小写字母的前 m ( m<=6) 个字符组成,请你计算出共有多少长度为 k( k<=6 ...
- 从Hash Killer I、II、III论字符串哈希
首先,Hash Killer I.II.III是BZOJ上面三道很经典的字符串哈希破解题.当时关于II,本人还琢磨了好久,但一直不明白为啥别人AC的代码都才0.3kb左右,直到CYG神犇说可以直接随机 ...
- Redis支持的数据类型及相应操作命令:String(字符串),Hash(哈希),List(列表),Set(集合)及zset(sorted set:有序集合)
help 命令,3种形式: help 命令 形式 help @<group> 比如:help @generic.help @string.help @hash.help @list.hel ...
- 字符串哈希hash
题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 友情提醒:如果真的想好好练习哈希的话,请自觉,否则请右转 ...
- 【基本算法入门-字符串哈希(Hash)】-C++
字符串哈希入门 说得通俗一点,字符串哈希实质上就是把每个不同的字符串转成不同的整数. 为什么会有这样的需要呢?很明显,存储一个超长的字符串和存储一个超大但是能存的下的整数,后者所占的空间会少的多,但主 ...
- Crazy Search POJ - 1200 (字符串哈希hash)
Many people like to solve hard puzzles some of which may lead them to madness. One such puzzle could ...
- 牛客练习赛33 E tokitsukaze and Similar String (字符串哈希hash)
链接:https://ac.nowcoder.com/acm/contest/308/E 来源:牛客网 tokitsukaze and Similar String 时间限制:C/C++ 2秒,其他语 ...
- luoguP3370 【模板】字符串哈希 [hash]
题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 友情提醒:如果真的想好好练习哈希的话,请自觉,否则请右转 ...
随机推荐
- 【C++】【图像处理】形态学处理(腐蚀、膨胀)算法解析(以.raw格式的图像为基础进行图像处理、gray levels:256)
1 void erosion(BYTE* image, int w, int h, BYTE* outImg) 2 { 3 int rept; 4 //腐蚀 5 memcpy(outImg, imag ...
- ElasticSearch之Index stats API
获取指定索引的统计数据. 获取指定索引的全部统计数据,命令样例如下: curl -X GET "https://localhost:9200/testindex_001/_stats?pre ...
- 《A Novel Table-to-Graph Generation Approach for Document-Level Joint Entity and Relation Extraction》阅读笔记
代码 原文地址 文档级关系抽取(DocRE)的目的是从文档中提取实体之间的关系,这对于知识图谱构建等应用非常重要.然而,现有的方法通常需要预先识别出文档中的实体及其提及,这与实际应用场景不一致 ...
- 用Spring Boot 3.2虚拟线程搭建静态文件服务器有多快?
Spring Boot 3.2 于 2023 年 11 月大张旗鼓地发布,标志着 Java 开发领域的一个关键时刻.这一突破性的版本引入了一系列革命性的功能,包括: 虚拟线程:利用 Project L ...
- Spring源码学习笔记5——注册BeanPostProcessor,初始化事件多播器,注册事件监听器
一丶前言 上篇Spring容器回调完所有的BeanFactoryPostPocessor,之后可以做到替换所有占位符,解析所有配置类等工作,这篇还会迎来一个Spring留给我们扩展的一个接口,涉及到A ...
- 《语义增强可编程知识图谱SPG》白皮书
语义増强可编程图谱框架:新一代知识图谱语义框架/引擎.SPG+LLM双驱架构及应用相关进展和应用.<语义增强可编程知识图谱SPG>白皮书 v1.0.pdf: https://url39.c ...
- 如何通过jstat命令进行查看堆内存使用情况?
摘要:jstat命令可以查看堆内存各部分的使用量,以及加载类的数量. 本文分享自华为云社区<JVM之通过jstat命令进行查看堆内存使用情况>,作者:共饮一杯无 . 基本概念 jstat是 ...
- 理论+实例,带你掌握Linux的页目录和页表
摘要:操作系统在加载用户程序的时候,不仅仅需要分配物理内存,来存放程序的内容:而且还需要分配物理内存,用来保存程序的页目录和页表. 本文分享自华为云社区<Linux从头学15:[页目录和页表]- ...
- .Net Core 跨域
Startup.cs public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseCorsMidd ...
- 在DataGrid中实现Button Command绑定
在DataGrid中实现Button Command绑定 Command="{Binding editCommand}" 会默认查找UserList中对象的属性,而你的UserLi ...