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 ...
随机推荐
- 写python获取android设备的GPS及姿态信息
在android上,我们可以使用QPython来编写.执行Python脚本.它对很多android 系统函数进行了方便的封装,使用QPython编写功能简单的小程序异常方便. 这个示例是我之前用来读取 ...
- 阶段3 2.Spring_06.Spring的新注解_7 spring整合junit问题分析
测试类重复代码的问题 这是之前的方式 运行findAll的方法,没有问题 测试人员不需要关心上面的方法,.应该关心的各个方法是否能够正常的运行 对于一个测试工程师,只要写完变量就可以测试了. 可以使用 ...
- Maximum Likelihood 最大似然估计
Maximum Likelihood 最大似然估计 这个算法解决的问题是,当我们知道一组变量的密度分布函数与从总体采样的个体的时候,需要估计函数中的某些变量. 假设概率密度函数如下: 一般来说,为了计 ...
- sql 查询某一列最大的数据
select colm1,Max(colm2),max(colm3) from table where condition group by colm1
- Professional JavaScript for Web Developers P224-P225
然后第二段代码执行过程中,有1个global variabe object,1个createFunction activation object,10个anonymous function1 acti ...
- WebApi使用二进制方式上传和下载文件
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; usi ...
- python学习之生函数名的理解
4.4.10 函数名的应用 函数名就是一个特殊的变量,后边跟上()之后可以执行函数: 1.作为一个变量使用 def func(): print('123') f1 = func f2 = f1 f1( ...
- 【Deep Learning Nanodegree Foundation笔记】第 1 课:INTRODUCTION Welcome
Welcome to the Deep Learning Nanodegree Foundations Program! In this lesson, you'll meet your instru ...
- win10序列号 2019年10月测试
win10序列号 N3415-266GF-AH13H-WA3UE-5HBT4 win10序列号 NPK3G-4Q81M-X4A61-D553L-NV68D win10序列号 N617H-84K11-6 ...
- DVWA、 DSVM 环境搭建简述
DVWA(http://www.dvwa.co.uk/)是一个本地的漏洞演示环境基于PHP和Mysql . 另外还有基于Python的DSVM部署起来也十分简单.(https://github.com ...