简介

Hash,将一个字符串映射到一个数字上。

计算Hash

计算Hash的方法有很多种,比如说在密码学中常用的 \(\texttt{MD5}\) 和 \(\texttt{SHA256}\) 等。

但是我们一般使用一个简单的方法:

  • 将字符串看成一个 \(B\) 进制数。(\(B \ge \textbf{字符集大小}\))
  • 将这个 \(B\) 进制数对 \(p\) 取模,要求 \(B,p\) 互质。

显然,如果有 \(p+1\) 个互不相同的字符串,那么一定有至少一对 \(\operatorname{Hash}\) 相等的字符串。

所以,\(p\) 一般都很大,如 \(2^{64},2^{63},10^{9}+7\) 等。

注:大多数情况下,\(10^{9}+7\) 仍然不够用,因为当有 \(\sqrt{p}\) 个字符串时,\(\operatorname{Hash}\) 相同(我们称之为Hash冲突)的概率就很高了。

Tip:在C++中,如果用 unsigned long long 来保存,那么可以考虑自然溢出,这样其实自带 \(p=2^{64}\)。

其实 \(p\) 最好为质数,但是一般不需要。

后文中,用 \(\operatorname{hash}(x)\) 表示字符串 \(x\) 的Hash值。

前缀Hash递推

预处理字符串 \(s\) 的所有前缀子串 \(s[1:i]\) 的Hash \(H[i]\),\(H\) 就是 \(s\) 的前缀Hash,后缀Hash同理。

那么有一个显然的递推公式:

\[H[i]=H[i-1]\times B+\operatorname{ToInteger}(s[i]) \pmod{p}
\]

前缀Hash可以处理以下问题:

  • 给出几个字符串,求一个模式串 \(s\) 是多少个字符串的前缀。

将所有字符串的前缀Hash求出来,合并成一个有序数组(或者 std::set),然后求出 \(\operatorname{hash}(s)\),将 \(\operatorname{hash}(s)\) 在那个数组/set上二分。

快速计算子串Hash

先使用上面章节的方法递推出前缀Hash \(H\)。

那么子串 \(s[l:r]\) 的Hash计算公式为:

\[\operatorname{hash}(s[l:r])=H[r]-H[l-1]\times B^{r-l+1} \pmod{p}
\]

就可以在 \(O(\log n)\)(如果使用光速幂就是 \(O(1)\))求字符串中的任意连续字串的hash了。

用Hash匹配字符串

如果 \(\operatorname{hash}(x)=\operatorname{hash}(y)\),那么 \(x=y\)。

由于hash冲突的存在,可能并不准确,但是只要 \(p\) 尽可能的大就行。

综合:P2852 [USACO06DEC]Milk Patterns G

给出一个长度为 \(n\) 数列 \(A\),问出现次数为 \(K\) 的字串长度最大是多少?

\(1 \le K \le n \le 20000,1 \le A_i \le 1000000\)

第一道没看题解A掉的紫题

正解SAM,但是可以用Hash水过。

预处理前缀Hash,二分字串长度 \(L\),对于每一个长度为 \(L\) 的子串计算Hash,用 std::unordered_map 统计一下就好。

时间复杂度 \(O(n\log^{2} n)\)。

代码:(写到一半二分不会写,还要请教@exited,雾)

#include <bits/stdc++.h>
#define DEBUGGING 1
#define debug(...) if(DEBUGGING){printf(__VA_ARGS__);putchar('\n');} using namespace std; int n,k;
int a[20005];
int l,r;
int mid;
unsigned long long qzhash[20005];
const int base =1000001;
const unsigned long long mod = 2e63; #define int unsigned long long
int pow(int a,int b,int mod) {
#define MAG (1ull)
int ans=1;
for(; b; b>>=1,a=MAG*a*a%mod) {
if(b&1) {
ans=MAG*ans*a%mod;
}
}
#undef MAG
return ans;
}
#undef int unsigned long long any_hash(int l,int r){
return (qzhash[r]-(qzhash[l-1]*pow(base,r-l+1,mod))%mod)%mod;
} unordered_map<unsigned long long,int> mmap;
int max_mm = 0; bool check(int length){
max_mm=0;
mmap.clear();
for(int l=1,r=length;l<=n&&r<=n;l++,r++){
unsigned long long current_hash=any_hash(l,r);
mmap[current_hash]++;
max_mm = max(max_mm, mmap[current_hash]);
}
return max_mm >= k;
}
int ans=0;
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
qzhash[i]=qzhash[i-1]*base%mod;
qzhash[i]+=a[i];
qzhash[i]%=mod;
}
l=1,r=n;
while(l<r){
mid=(l+r)>>1;
if(check(mid)){
l=mid+1;
ans=mid;
}
else{
r=mid;
}
}
cout<<ans;
return 0;
}

Hash——温暖人心的算法的更多相关文章

  1. 【bzoj3207】花神的嘲讽计划Ⅰ Hash+STL-map+莫队算法

    题目描述 背景 花神是神,一大癖好就是嘲讽大J,举例如下: “哎你傻不傻的![hqz:大笨J]” “这道题又被J屎过了!!” “J这程序怎么跑这么快!J要逆袭了!” …… 描述 这一天DJ在给吾等众蒟 ...

  2. consistent hash(一致性哈希算法)

    一.产生背景 今天咱不去长篇大论特别详细地讲解consistent hash,我争取用最轻松的方式告诉你consistent hash算法是什么,如果需要深入,Google一下~. 举个栗子吧: 比如 ...

  3. hash算法总结收集

    hash算法的意义在于提供了一种快速存取数据的方法,它用一种算法建立键值与真实值之间的对应关系,(每一个真实值只能有一个键值,但是一个键值可以对应多个真实值),这样可以快速在数组等条件中里面存取数据. ...

  4. 常见hash算法的原理

    散列表,它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法.顾名思义,该数据结构可以理解为一个线性表,但是其中的元素不是紧密排列的,而是可能存在空隙. 散列表(Hash table,也叫 ...

  5. PHP中各种Hash算法性能比较

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  6. 分布式算法(一致性Hash算法)

    一.分布式算法 在做服务器负载均衡时候可供选择的负载均衡的算法有很多,包括: 轮循算法(Round Robin).哈希算法(HASH).最少连接算法(Least Connection).响应速度算法( ...

  7. Hash算法入门指南(聊点不一样的算法人生)

    前言 很多人到现在为止都总是问我算法该怎么学啊,数据结构好难啊怎么的,学习难度被莫名的夸大了,其实不然.对于一个学计算机相关专业的人都知道,数据结构是大学的一门必修课,数据结构与算法是基础,却常常容易 ...

  8. 几种常用hash算法及原理

    计算理论中,没有Hash函数的说法,只有单向函数的说法.所谓的单向函数,是一个复杂的定义,大家可以去看计算理论或者密码学方面的数据.用“人 类”的语言描述单向函数就是:如果某个函数在给定输入的时候,很 ...

  9. 海量数据挖掘MMDS week2: 频繁项集挖掘 Apriori算法的改进:基于hash的方法

    http://blog.csdn.net/pipisorry/article/details/48901217 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...

  10. logging日志模块,hashlib hash算法相关的库,

    logging: 功能完善的日志模块 import logging #日志的级别 logging.debug("这是个调试信息")#级别10 #常规信息 logging.info( ...

随机推荐

  1. 是什么让.NET7的Min和Max方法性能暴增了45倍?

    简介 在之前的一篇文章.NET性能系列文章一:.NET7的性能改进中我们聊到Linq中的Min()和Max()方法.NET7比.NET6有高达45倍的性能提升,当时Benchmark代码和结果如下所示 ...

  2. vue Excel导入,下载Excel模板,导出Excel

    vue  Excel导入,下载Excel模板,导出Excel vue  Excel导入,下载Excel模板 <template> <div style="display: ...

  3. 三、Kubernetes调度

    一.Kubernetes调度 Scheduler 是 kubernetes 的调度器,主要的任务是把定义的 pod 分配到集群的节点上.听起来非常简单,但有很多要考虑的问题: 公平:如何保证每个节点都 ...

  4. Spring Cloud 整合 nacos 实现动态配置中心

    上一篇文章讲解了Spring Cloud 整合 nacos 实现服务注册与发现,nacos除了有服务注册与发现的功能,还有提供动态配置服务的功能.本文主要讲解Spring Cloud 整合nacos实 ...

  5. Python基础部分:11、文件和光标移动

    目录 一.文件操作 1.文件的概念 2.代码打开文件的方式 二.文件读写模式 1.'r' 只读模式 read 2.'w' 只写模式 write 3.'a' 尾部追写模式 add 三.文件操作模式 1. ...

  6. 小程序利用canvas 绘制图案 (生成海报, 生成有特色的头像)

    小程序利用canvas 绘制图案 (生成海报, 生成有特色的头像) 微信小程序生成特色头像,海报等是比较常见的.下面我来介绍下实现该类小程序的过程. 首先选择前端来通过 canvas 绘制.这样比较节 ...

  7. 使用DOS命令运行JAVA项目

    使用DOS命令运行JAVA项目 找到生成项目的文件夹: 在地址前加上cmd+空格,进入命令窗口: 输入javac 类的名称.java,生成class文件: 输入java 类的名称: 运行成功:

  8. DevOps | 企业内源(内部开源)适合什么样的公司

    框架类是否适合企业内源? 框架类都由公司早期来的一些大佬们负责(相当于技术委员会),更新频率非常低.给框架类提MR的人,多数本身就在技术委员会. 如果公司的人员众多,类似BAT级别,几万人使用的框架, ...

  9. PHP实现CURL发送请求

    public function curl($url, $params = false, $ispost = 0) { $httpInfo = array(); //初始化 $ch = curl_ini ...

  10. Go语言核心36讲37

    你好,我是郝林,今天我们继续来分享并发安全字典sync.Map的内容. 我们在上一篇文章中谈到了,由于并发安全字典提供的方法涉及的键和值的类型都是interface{},所以我们在调用这些方法的时候, ...