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 ...
随机推荐
- Application 使用分析
一. Application 分析 1. Application 简介 (1) Application 概念 Application 概念 : Application 属于组件范畴; -- 本质 : ...
- okgo网络请求框架的实现
第一步:添加依赖: implementation 'com.lzy.net:okgo:3.0.4' implementation 'com.lzy.net:okrx2:2.0.2' implement ...
- scrollView 嵌套 listview 方式除了测量还有什么方法?
1.手动设置 ListView 高度经过测试发现,在 xml 中直接指定 ListView 的高度,是可以解决这个问题的,但是 ListView中的数据是可变的,实际高度还需要实际测量.于是手动代码设 ...
- Sublime Text 3 相关
Sublime Text 3 相关 Sublime Text 3是款非常实用代码编辑神器,但是想要用任何一款软件,掌握一些快捷键还是很有必要的.. 将Sublime Text 3 添加到右键选项中 打 ...
- ELK+Kafka日志收集环境搭建
1.搭建Elasticsearch环境并测试: (1)删除es的容器 (2)删除es的镜像 (3)宿主机调内存: 执行命令:sudo sysctl -w vm.max_map_count=655360 ...
- spring实战第五版总结
- POJ3585 Accumulation Degree【换根dp】
题目传送门 题意 给出一棵树,树上的边都有容量,在树上任意选一个点作为根,使得往外流(到叶节点,叶节点可以接受无限多的流量)的流量最大. 分析 首先,还是从1号点工具人开始$dfs$,可以求出$dp[ ...
- centos7成功部署OpenLDAP
目录 一.部署OpenLDAP. 1 1.安装openLDAP. 1 2.设置openldap管理员密码... 1 3.更改openldap配置... 2 4.更改监控认证配置... 2 5.设置DB ...
- flask 必知必会
在局域网中让其它电脑访问我的网站 from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): re ...
- Redis配置主从时报错“Could not connect to Redis at 192.168.0.50:6379: Connection refused not connected>”
配置Redis主从时,修改完从节点配置文件,然后报错 [root@Rich七哥-0-50 redis]# /opt/redis/redis-cli -h 192.168.0.50 Could not ...