Hash基础
BKDR Hash:
选取恰当的进制,可以把字符串中的字符看成一个大数字中的每一位数字,不过比较字符串和比较大数字的复杂度并没有什么区别
首先不要把任意字符对应到数字0,比如假如把a对应到数字0,那么将不能只从Hash结果上区分ab和b(虽然可以额外判断字符串长度,但不把任意字符对应到数字0更加省事且没有任何副作用),一般而言,把a-z对应到数字1-26比较合适。
关于进制的选择实际上非常自由,大于所有字符对应的数字的最大值,不要含有模数的质因数,比如一个字符集是a到z的题目,选择27、233、19260817都是可以的。
模数的选择(尽量还是要选择质数):
绝大多数情况下,不要选择一个109级别的数,因为这样随机数据都会有Hash冲突,根据生日悖论,随便找上109−−−√109个串就有大概率出现至少一对Hash 值相等的串(参见BZOJ 3098 Hash Killer II)。
最稳妥的办法是选择两个109级别的质数,只有模这两个数都相等才判断相等,但常数略大,代码相对难写,目前暂时没有办法卡掉这种写法(除了卡时间让它超时)(参见BZOJ 3099 Hash Killer III)。
如果能背过或在考场上找出一个1018级别的质数(Miller-Rabin),也相对靠谱,主要用于前一种担心会被卡,后一种担心超时。
偷懒的写法就是直接使用unsigned long long,不手动进行取模,它溢出时会自动对264(自然溢出也可以被卡)
用luogu P3370为例。
自然溢出hash(100)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
ull base=;
ull a[];
char s[];
int n,ans=;
ull hashs(char s[])
{
int len=strlen(s);
ull ans=;
for (int i=;i<len;i++)
ans=ans*base+(ull)s[i];
return ans&0x7fffffff;
}
main()
{
scanf("%d",&n);
for (int i=;i<=n;i++)
{
scanf("%s",s);
a[i]=hashs(s);
}
sort(a+,a+n+);
for (int i=;i<=n;i++)
if (a[i]!=a[i-])
ans++;
printf("%d\n",ans);
}
单模数hash(80)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
ull base=;
ull a[];
char s[];
int n,ans=;
ull mod=;
ull hashs(char s[])
{
int len=strlen(s);
ull ans=;
for (int i=;i<len;i++)
ans=(ans*base+(ull)s[i])%mod;
return ans;
}
main()
{
scanf("%d",&n);
for (int i=;i<=n;i++)
{
scanf("%s",s);
a[i]=hashs(s);
}
sort(a+,a+n+);
for (int i=;i<=n;i++)
if (a[i]!=a[i-])
ans++;
printf("%d\n",ans);
}
双hash
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
ull base=;
struct data
{
ull x,y;
}a[];
char s[];
int n,ans=;
ull mod1=;
ull mod2=;
ull hash1(char s[])
{
int len=strlen(s);
ull ans=;
for (int i=;i<len;i++)
ans=(ans*base+(ull)s[i])%mod1;
return ans;
}
ull hash2(char s[])
{
int len=strlen(s);
ull ans=;
for (int i=;i<len;i++)
ans=(ans*base+(ull)s[i])%mod2;
return ans;
}
bool comp(data a,data b)
{
return a.x<b.x;
}
main()
{
scanf("%d",&n);
for (int i=;i<=n;i++)
{
scanf("%s",s);
a[i].x=hash1(s);
a[i].y=hash2(s);
}
sort(a+,a+n+,comp);
for (int i=;i<=n;i++)
if (a[i].x!=a[i-].x || a[i-].y!=a[i].y)
ans++;
printf("%d\n",ans);
}
只用一个10^18质数的hash(100)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
ull base=;
ull a[];
char s[];
int n,ans=;
ull mod=212370440130137957ll;
ull hashs(char s[])
{
int len=strlen(s);
ull ans=;
for (int i=;i<len;i++)
ans=(ans*base+(ull)s[i])%mod;
return ans;
}
main()
{
scanf("%d",&n);
for (int i=;i<=n;i++)
{
scanf("%s",s);
a[i]=hashs(s);
}
sort(a+,a+n+);
for (int i=;i<=n;i++)
if (a[i]!=a[i-])
ans++;
printf("%d\n",ans);
}
例题:http://www.yhzq-blog.cc/%E5%AD%97%E7%AC%A6%E4%B8%B2hash%E6%80%BB%E7%BB%93/
Hash基础的更多相关文章
- i春秋DMZ大型靶场实验(四)Hash基础
下载工具包 打开目标机 通过目录爆破发现 phpmyadmin 在登录位置尝试注入 返现 可以注入 直接上sqlmap 上 bp 代理抓包 sqlmap.py -r bp.txt ...
- Redis 源码简洁剖析 03 - Dict Hash 基础
Redis Hash 源码 Redis Hash 数据结构 Redis rehash 原理 为什么要 rehash? Redis dict 数据结构 Redis rehash 过程 什么时候触发 re ...
- redis字典快速映射+hash釜底抽薪+渐进式rehash | redis为什么那么快
前言 相信你一定使用过新华字典吧!小时候不会读的字都是通过字典去查找的.在Redis中也存在相同功能叫做字典又称为符号表!是一种保存键值对的抽象数据结构 本篇仍然定位在[redis前传]系列中,因为本 ...
- 最新Android面试题集锦
近期由于某些原因想换工作,整理一下个人认为面试中还比較值得记录的一些题目,给须要找这方面工作的人一个借鉴. 下面基本仅仅记录题目或者大概答案,假设大家有比較具体的解答或者比較好的面试题木,希望各位看到 ...
- 面试必问:HashMap 底层实现原理
HashMap是在面试中经常会问的一点,很多时候我们仅仅只是知道HashMap他是允许键值对都是Null,并且是非线程安全的,如果在多线程的环境下使用,是很容易出现问题的. 这是我们通常在面试中会说的 ...
- python学习之操作redis
一.Redis安装网上很多可以查找 二.redis-py的安装,使用命令pip install redis. 安装过程中如果产生连接超时的错误,可以使用国内镜像参考如下 豆瓣:pip install ...
- Redis 实战 —— 01. Redis 数据结构简介
一些数据库和缓存服务器的特性和功能 P4 名称 类型 数据存储选项 查询类型 附加功能 Redis 使用内存存储(in-memory)的非关系数据库 字符串.列表.哈希表.集合.有序集合 每种数据类型 ...
- Redis 源码简洁剖析 07 - main 函数启动
前言 问题 阶段 1:基本初始化 阶段 2:检查哨兵模式,执行 RDB 或 AOF 检测 阶段 3:运行参数解析 阶段 4:初始化 server 资源管理 初始化数据库 创建事件驱动框架 阶段 5:执 ...
- 最基础的Hash
type thash=^node; node=record state:longint; next:thash; end; var a,i:longint; p:thash; hash:..]of t ...
随机推荐
- VS2017 -error LNK1104: 无法打开文件“msvcprtd.lib”
原文地址:https://blog.csdn.net/u012308586/article/details/89309495 VS2017 -error LNK1104 无法打开文件“msvcprtd ...
- centos7 系統vps安裝mysql5.6及設置本地遠程連接筆記
用xshell連接上vps 1,下载mysql的repo源 wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm su ...
- Java的前后端需要了解些什么?
一.Java概念 Java具有简单性.面向对象.分布式.健壮性.安全性.平台独立与可移植性.多线程.动态性等特点.Java可以编写桌面应用程序.Web应用程序.分布式系统和嵌入式系统应用程序等. Ja ...
- 配置java开发环境,存在多个版本JDK时,怎样让所需版本生效
我本地有个1.7.0的java版本,后来我新装了一个13的版本,但是命令行查java版本的时候,生效的还是1.7.0的版本,经过资料查询以及自身亲测,现将过程记录如下: 1.电脑右键选择--属性--高 ...
- iview Upload组件多个文件上传
使用 iview Upload 上传组件 手动上传 包括单个文件和多个文件 思路:创建一个数组 把需要上传的文件 push到这个数组里面 1.引用组件 2.手动上传,根据官方文档 设置:before ...
- DataGridViewCheckBoxColumn的Value值和EditFormatedValue值不一致
今天要做一个代码修改DataGridViewCheckBoxColumn的Value值然后再遍历获取DataGridview选中项,因为遍历的时候为了能获取跟界面一致的选项,所以判断是否选中使用的是E ...
- javascript中,一个js中的函数,第一句var _this = this;为什么要这样做?
javascript中,一个js中的函数,第一句var _this = this;为什么要这样做? 下面是源码: 下面这段代码是常用的网站首页,自动切换span或者tabbar来变更List显示内容的 ...
- hive排错
找出错的那个hive实例,看错误日志: 点下面stdout,找Error
- 快速安装create-react-app脚手架
create-react-app搭建react项目:https://blog.csdn.net/weixin_41077029/article/details/82622106 快速安装create- ...
- 洛谷 P1879 玉米田Corn Fields 题解
题面 一道思维难度不大的状态压缩,也并不卡常,但细节处理要格外注意: f[i][j]表示前i行最后一行状态是j的方案数 #include <bits/stdc++.h> #define p ...