【C++天梯计划】1.8 哈希算法(hash)
创始人
2024-01-31 20:02:24

文章目录

    • 什么是哈希算法?
    • 哈希基本概念
    • 哈希算法性质
    • 例题1:子串判重
        • 题目描述
        • 输入
        • 输出
        • 输入输出样例
        • 思路
        • 代码
    • 例题2:三个火枪手
        • 题目描述
        • 输入
        • 输出
        • 输入输出样例
        • 思路
        • 代码

🎆🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎆
今天我要开启一个新计划----【C++天梯计划】
目的是通过天梯计划,通过题目和知识点串联的方式,完成C++复习与巩固。

什么是哈希算法?

哈希算法,一般翻译做散列、杂凑,或音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

哈希基本概念

若结构中存在和关键字K相等的记录,则必定在f(K)的存储位置上。由此不需比较便可直接取得所查记录。称这个对应关系f为散列函数(Hash function)按这个事先建立的表为散列表。

对不同的关键字可能得到同一散列地址,即key1≠key2,而f(key1)=f(key2),这种现象称碰撞。具有相同函数值的关键字对该散列函数来说称做同义词。综上所述,根据散列函数H(key)和处理冲突的方法将一组关键字映射到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“象” 作为记录在表中的存储位置,这种表便称为散列表,这一映象过程称为散列造表或散列,所得的存储位置称散列地址。

若对于关键字集合中的任一个关键字,经散列函数映象到地址集合中任何一个地址的概率是相等的,则称此类散列函数为均匀散列函数(Uniform Hash function),这就是使关键字经过散列函数得到一个“随机的地址”,从而减少冲突。

哈希算法性质

所有散列函数都有如下一个基本特性:如果两个散列值是不相同的(根据同一函数),那么这两个散列值的原始输入也是不相同的。这个特性是散列函数具有确定性的结果。但另一方面,散列函数的输入和输出不是一一对应的,如果两个散列值相同,两个输入值很可能是相同的,但不绝对肯定二者一定相等(可能出现哈希碰撞)。输入一些数据计算出散列值,然后部分改变输入值,一个具有强混淆特性的散列函数会产生一个完全不同的散列值。
典型的散列函数都有无限定义域,比如任意长度的字节字符串,和有限的值域,比如固定长度的比特串。在某些情况下,散列函数可以设计成具有相同大小的定义域和值域间的一一对应。一一对应的散列函数也称为排列。可逆性可以通过使用一系列的对于输入值的可逆“混合”运算而得到。

例题1:子串判重

题目描述

给定一个含有 2626 个小写英文字母的字符串。有 mm 次询问,每次给出 22 个区间,请问这两个区间里的子字符串是否一样?

输入

第一行输入一个字符串 SS 。
第二行一个数字 mm,表示 mm 次询问。
接下来 mm 行,每行四个数字 l1,r1,l2,r2l1,r1,l2,r2 ,分别表示此次询问的两个区间,注意字符串的位置从1开始编号。
数据范围:
1≤length(S),m,l1,r1,l2,r2≤10000001≤length(S),m,l1,r1,l2,r2≤1000000。

输出

对于每次询问,输出一行表示结果。
如果两个子串完全一样,输出 Yes,否则输出 No(注意大小写)。

输入输出样例

输入
aabbaabb
3
1 3 5 7
1 3 6 8
1 2 1 2
输出
Yes
No
Yes

思路

字符串哈希问题,注意本题数据量较大,因此不要循环字符串时求字符串长度,如果在循环中求,循环一次,求解一次,效率很低。

代码

#include 
using namespace std;const int N = 1e6 +10,P = 131;
typedef unsigned long long ULL;
int m;
char s[N];
ULL h[N],p[N];//求子串的哈希
ULL fun(int l,int r){return h[r] - h[l-1] * p[r-l+1];
} int main(){scanf("%s%d",s+1,&m);//下标从1开始取p[0] = 1;//计算次数过多,不用每次循环都求一次长度int len = strlen(s+1); //预处理前缀和,以及p^n for(int i = 1;i <= len;i++){p[i] = p[i-1] * P;h[i] = h[i-1] * P + s[i]-'a'+1;} int l1,r1,l2,r2;while(m--){scanf("%d%d%d%d",&l1,&r1,&l2,&r2);if(fun(l1,r1)==fun(l2,r2)) printf("Yes\n");else printf("No\n");}return 0;
}

例题2:三个火枪手

题目描述

三个火枪手阿多斯、波尔多斯、阿拉密斯要给好朋友达达尼昂留下一份加密的信息。
阿多斯写出他们要留下的仅包含大写字母的字符串 AA ,波尔多斯将这个字符串复制了一遍,得到字符串 BB,阿拉密斯在字符串 BB 的任意一个位置(也可以在首尾的位置)插入一个大写字母得到最终的字符串 CC。
现给定字符串 CC,请编程计算出最初的字符串 AA。

输入

第 11 行输入一个整数 NN,代表字符串 CC 的长度;
第 22 行读入一个长度为 NN 的字符串 CC;

输出

输出计算出的字符串 AA;
请注意,可能由于波尔多斯、阿拉密斯的失误,得到最终得到的字符串 CC 有误,导致无法还原出字符串 AA,这种情况下,请输出NOT POSSIBLE;
也有可能计算发现无法唯一的还原出字符串 AA,这种情况下,请输出 NOT UNIQUE。

输入输出样例

输入
7
XYAZXYZ
输出
XYZ
输入
7
ABCDEFG
输出
NOT POSSIBLE
输入
9
ABABABABA
输出
NOT UNIQUE

思路

例如有字符串 XYAZXYZXYAZXYZ ,枚举每个位置,将每个位置删除后,计算出剩余字符串各一半的哈希值,比较是否相等。
要注意特殊情况,比如字符串 AAAAAAAAAAAAAA,虽然删除每个位置都是可以的,但要注意,得到的解是唯一的,因此不能以可以删除位置的数量作为判断答案是否唯一的标准;可以用删除一个字符后,剩余字符串一半字符的哈希值,作为判断答案唯一的标准。

代码

#include
using namespace std;typedef unsigned long long ULL;
const int N = 2.5e6 + 10,P = 131;
char s[N];
ULL p[N],h[N];
set st;//记录哈希值 
int n;void gethash() {p[0] = 1;for(int i = 1; i <= n; i++) {p[i] = p[i-1] * P;h[i] = h[i-1] * P + (s[i] - 'A' + 1);}
}ULL get(int l,int r) {if(l > r) return 0;return h[r] - h[l-1] * p[r - l + 1];
}int main() {scanf("%d%s",&n,s+1);gethash();//计算哈希值//枚举每个可能被删除的字符ULL l,r;int c = 0,mid = n / 2 + 1;char res = ' ';for(int i = 1; i <= n; i++) {//拼出前后两半的哈希值if (i == 1) {l = get(2, mid);r = get(mid + 1, n);} else if(i == n) {l = get(1, mid - 1);r = get(mid, n - 1);}else if(i < mid) {l = get(1,i-1) * p[mid-(i+1)+1] + get(i+1,mid);r = get(mid+1,n);} else if(i > mid) {l = get(1,mid - 1);r = get(mid+1,i-1) * p[n-(i+1)+1] + get(i+1,n);} else if(i == mid) {l = get(1,mid - 1);r = get(mid + 1,n);}if(l == r) {st.insert(l);if(st.size() > 1) {printf("NOT UNIQUE\n");return 0;}//判断答案是哪一半if(i <= mid) res = 'R';//右侧一半else res = 'L';//左侧一半}}if(st.size() == 0) printf("NOT POSSIBLE");else {s[mid] = '\0';if(res == 'L') printf("%s",s+1);else printf("%s",s+mid+1);}return 0;
}

相关内容

热门资讯

猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
crush是什么意思 女生说她... 之前,在国外网站BuzzFeed的编辑在推特上向英语文字爱好者征集"颜值最高"的英文单词。这10个单...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
地球属于哪个星系 整个银河系只... 地球是人类在宇宙中的家园。以前人们认为地球是宇宙的中心。现在我们知道,地球并不是宇宙的中心。地球只是...