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 ...
随机推荐
- Error-ASP.NET:The Value of property CloneFrom can not be empty string!
ylbtech-Error-ASP.NET:The Value of property CloneFrom can not be empty string! 1.返回顶部 1. “/”应用程序中的服务 ...
- 多变量线性回归时使用梯度下降(Gradient Descent)求最小值的注意事项
梯度下降是回归问题中求cost function最小值的有效方法,对大数据量的训练集而言,其效果要 好于非迭代的normal equation方法. 在将其用于多变量回归时,有两个问题要注意,否则会导 ...
- 内网每一台电脑的外网ip是一样吗
内网每一台电脑上网的IP地址是一样的,因为公网地址的稀缺性,所以内部上网是通过映射或者说叫端口复用将内部私有地址转换为公有地址进行上网的. 公有地址就是网关设备出口的地址,也可以说是路由器的出口地址, ...
- Python_元组、字典内建方法详解
目录 目录 前言 软件环境 元组Tuple count 查询一个元素在Tuple中的数量 index 查询元素在Tuple中的索引号 元组的遍历 字典Dictionary 创建一个字典对象 简单的创建 ...
- 无界面上(linux)运行jmeter(2)
无界面上(linux)运行jmeter 1.先在bin目录下面创建一个文件夹testplan用来存放脚本(.jmx文件),然后在创建一个文件夹testresult用来存放脚本执行后的结果(.jtl文件 ...
- conftest.py作用范围
前言 一个测试工程下是可以有多个conftest.py的文件,一般在工程根目录放一个conftest.py起到全局作用.在不同的测试子目录也可以放conftest.py,作用范围只在该层级以及以下目录 ...
- Go(03) slice切片的使用
原文链接 http://www.limerence2017.com/2019/05/08/golang05/#more golang 的引用类型和内置类型变量 golang 中变量类型分为引用类型和值 ...
- 使用 Blender* 重新拓扑 VR 和游戏素材
本文介绍如何将网格重新拓扑成一个整洁的低密度模型,然后 UV 解包该网格,以便将纹理贴添加至新模型.本文还将探讨如何使用免费工具,比如 Blender* 及其 Bsurface 插件,重新拓扑雕塑的 ...
- 20个python项目--图片转字符画
转自实验楼:https://www.shiyanlou.com/courses/370/learning/?id=1191 代码: # -*- coding:utf-8 -*- from PIL im ...
- c语言l博客作业04
这作业属于那个课程 c语言程序设计ll 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-4/homework/9772 我在这个课程的目标 ...