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基础的更多相关文章

  1. i春秋DMZ大型靶场实验(四)Hash基础

    下载工具包  打开目标机 通过目录爆破发现 phpmyadmin    在登录位置尝试注入 返现 可以注入 直接上sqlmap    上 bp 代理抓包 sqlmap.py  -r  bp.txt  ...

  2. Redis 源码简洁剖析 03 - Dict Hash 基础

    Redis Hash 源码 Redis Hash 数据结构 Redis rehash 原理 为什么要 rehash? Redis dict 数据结构 Redis rehash 过程 什么时候触发 re ...

  3. redis字典快速映射+hash釜底抽薪+渐进式rehash | redis为什么那么快

    前言 相信你一定使用过新华字典吧!小时候不会读的字都是通过字典去查找的.在Redis中也存在相同功能叫做字典又称为符号表!是一种保存键值对的抽象数据结构 本篇仍然定位在[redis前传]系列中,因为本 ...

  4. 最新Android面试题集锦

    近期由于某些原因想换工作,整理一下个人认为面试中还比較值得记录的一些题目,给须要找这方面工作的人一个借鉴. 下面基本仅仅记录题目或者大概答案,假设大家有比較具体的解答或者比較好的面试题木,希望各位看到 ...

  5. 面试必问:HashMap 底层实现原理

    HashMap是在面试中经常会问的一点,很多时候我们仅仅只是知道HashMap他是允许键值对都是Null,并且是非线程安全的,如果在多线程的环境下使用,是很容易出现问题的. 这是我们通常在面试中会说的 ...

  6. python学习之操作redis

    一.Redis安装网上很多可以查找 二.redis-py的安装,使用命令pip install redis. 安装过程中如果产生连接超时的错误,可以使用国内镜像参考如下 豆瓣:pip install ...

  7. Redis 实战 —— 01. Redis 数据结构简介

    一些数据库和缓存服务器的特性和功能 P4 名称 类型 数据存储选项 查询类型 附加功能 Redis 使用内存存储(in-memory)的非关系数据库 字符串.列表.哈希表.集合.有序集合 每种数据类型 ...

  8. Redis 源码简洁剖析 07 - main 函数启动

    前言 问题 阶段 1:基本初始化 阶段 2:检查哨兵模式,执行 RDB 或 AOF 检测 阶段 3:运行参数解析 阶段 4:初始化 server 资源管理 初始化数据库 创建事件驱动框架 阶段 5:执 ...

  9. 最基础的Hash

    type thash=^node; node=record state:longint; next:thash; end; var a,i:longint; p:thash; hash:..]of t ...

随机推荐

  1. leetcode 188. 买卖股票的最佳时机 IV

    参见 本题采用了第一列初始化后,从左侧向右开始递推的方式,但从上往下递推应该也成立,以后尝试一下 想写一个普适性的适用于n天交易k次持有j股的状态方程但是有问题:对于交易次数过多的情况数组会超出界限: ...

  2. Serializable 和 Parcelable 的区别?

    1.在使用内存的时候,Parcelable 类比 Serializable 性能高,所以推荐使用 Parcelable 类.2.Serializable 在序列化的时候会产生大量的临时变量,从而引起频 ...

  3. Service 是否在 main thread 中执行, service 里面是否能执行耗时的操作?

    默认情况,如果没有显示的指 service 所运行的进程, Service 和 activity 是运行在当前 app 所在进程的 main thread(UI 主线程)里面.service 里面不能 ...

  4. 第一章 SpringCloud简介

    1.架构演进与微服务 单体架构:一个归档包包含所有的功能的应用程序. 缺点: 复杂性逐渐变高 技术债务逐渐上升 部署速度逐渐变慢 阻碍技术创新 无法按需伸缩 架构演进: 单体架构 SOA 微服务 微服 ...

  5. 阶段3 2.Spring_10.Spring中事务控制_9 spring编程式事务控制1-了解

    编程式的事物控制,使用的情况非常少,主要作为了解 新建项目 首先导入包坐标 复制代码 这里默认值配置了Service.dao和连接池其他的内容都没有配置 也就说现在是没有事物支持的.运行测试文件 有错 ...

  6. python3.6+RF环境搭建

    现在大家都在用python3了,利用这个机会正好把自己的练习重新整理一遍,本篇记录用python3.6重新搭建关键字驱动环境 目录 1.安装python3.6 2.安装wxPython 3.安装rob ...

  7. MySQL备份工具之mysqlhotcopy

    mysqlhotcopy使用lock tables.flush tables和cp或scp来快速备份数据库.它是备份数据库或单个表最快的途径,完全属于物理备份,但只能用于备份MyISAM存储引擎和运行 ...

  8. abap seach help 搜索帮助

    ABAP 的搜索帮助有很多种方法,掌握下面的几种基本差不多了 *&--------------------------------------------------------------- ...

  9. yum 安装docker后 无法启动

    一,yum安装docker yum -y install docker 启动docker service docker start 报错: journalctl -xe Error starting ...

  10. 【神经网络与深度学习】【Matlab开发】caffe-windows使能Matlab2015b接口

    [神经网络与深度学习][Matlab开发]caffe-windows使能Matlab2015b接口 标签:[神经网络与深度学习] [Matlab开发] 主要是想全部来一次,所以使能了Matlab的接口 ...