双值Hash

简单介绍

  • Hash的应用:Hash其实就像一个加密过程,很多加密算法都会用到Hash,像GitHub中生成的token值也是Hash的结果。

  • Hash冲突:简单来说就是不同的数映射到了同一个值,防止碰撞的最有效方法就是扩大Hash值的取值空间,也就是最好选用一个大质数(具体原因参考生日悖论/生日攻击:生日攻击是一个计算机密码学中的术语)。

  • 数学原型生日问题:一个班需要多少人,能保证有两个人的生日是一样的。鸽笼原理可能会得出366人,但是实际情况远少于366。这意味着Hash碰撞的可能性远比想象的高,实际上有一个近似的公式\(\sqrt{\frac{\pi}{2}N}\)可以算出50%Hash碰撞所需要的计算次数。这个公式告诉我们Hash碰撞所需耗费的计算次数,和取值空间的平方根是一个数量级。

进入正题

双值Hash就是用两个不同的mod值来计算Hash,如果两个Hash值都相等才认为是同一个字符串,Hash冲突概率降低了很多,但是常数大,容易被卡。时间上:自然溢出法<单Hash+大质数<双Hash+大质数。

  • Hash的几个常用公式:(虽然说本题不需要用到)

    • Hash递推:

      Hash[0]=0;
      Hash[i]=(Hash[i-1]*p+s[i]-'a'+1)%mod;
    • 区间Hash值:

      Hash[L...R]=(Hash[R]-Hash[L]*p^(R-L+1)+mod)%mod;这里减法可能会溢出

使用Hash的几个需要注意的地方

  • 在复杂度允许的情况下,尽量采用多Hash(不过一般双值Hash就够)

  • 比赛时能不用自然溢出就不要(平时刷题如果用自然溢出被卡可以及时换掉,但是比赛时如果用自然溢出,OI赛制就GG了)

  • 模数用大质数这个不用说了

  • 并且进制数不要选太简单的,比如 233和 13131 这样的,尽量大一点,比如1313131和233333,太小容易被卡。

  • 以及要合理应对各种卡hash方法的最好方法就是自己去卡一遍hash,详情请参考BZOJ hash killer系列。(各位巨佬可以尝试一下hash killer 3啊233333)

例题

题目链接:

给出N个字符串,输出不同字符串的个数。

#include <iostream>
#include <cstring>
#include <algorithm> using namespace std;
typedef unsigned long long ull;
const ull mod1=212370440130137957ll;
const ull mod2=(1<<30);
const int maxn=10001;
const int base=233333;
char a[maxn];
int n;
struct node{ull x,y;
bool operator < (const node& a)const{
return a.x==x?a.y<y:a.x<x;
}
}f[maxn];
inline ull hash1(char s[]){
ull ans=0,len=strlen(s);
for(int i=0;i<len;++i)ans=(ans*base+(ull)s[i])%mod1;
return ans;
}
inline ull hash2(char s[]){
ull ans=0,len=strlen(s);
for(int i=0;i<len;++i)ans=(ans*base+(ull)s[i])%mod2;
return ans;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%s",a);
f[i].x=hash1(a);
f[i].y=hash2(a);
//cout<<f[i].x<<" "<<f[i].y<<endl;
}
sort(f+1,f+1+n);
int ans=0;
for(int i=1;i<=n;++i){
if(f[i].x!=f[i+1].x||f[i].y!=f[i+1].y)ans++;//非相同字符串两个Hash值同时相等的概率非常小
}
printf("%d\n",ans);
return 0;
}

最新文章

  1. 支持高并发的IIS Web服务器常用设置
  2. ubuntu qtcreator 硬件权限问题
  3. BZOJ3442: 学习小组
  4. Jquery&amp;JS简单选项卡
  5. Cocos2d-x内存管理研究&lt;二&gt;
  6. jQuery提交Json数据到Webservice,并接收返回的Json数据
  7. ios开发:GCD多线程
  8. java基础学习总结六(对象与类、类的属性与方法)
  9. Oracle SQL 基础学习
  10. 深夜,用canvas画一个时钟
  11. background系列属性
  12. Arduino LiquidCrystal Library Bug Report #174181
  13. 【Luogu2458】保安站岗(动态规划)
  14. C语言之多线程机制(程序可以同时被执行而不会相互干扰)
  15. 阿里云CentOS7.2卸载CDH5.12
  16. 修改/dev/shm大小 tmps
  17. Python基础-python基本语法(二)
  18. codeforces146A
  19. C++中的内存区域及其性能特征
  20. Python知识

热门文章

  1. 十三、LVM 逻辑卷管理
  2. Linux快速编译
  3. Csdn账号如何注销?
  4. 012-Spring Boot web【一】web项目搭建、请求参数、RestController、使用jsp、freemarker,web容器tomcat和jetty
  5. vector swap
  6. 14Flutter StatefulWidget有状态组件、页面上绑定数据、改变页面数据、实现计数器功能、动态列表
  7. 比特币 难度值(difficulty)
  8. 反向代理远端 单台tomcat 使用域名代理
  9. Spring Security(1):认证和授权的核心组件介绍及源码分析
  10. lexicalized Parsing