hash 算法是一种加密算法,是将一个数据转换为一个标志,这个标志和源数据有十分紧密的关系。
hash 算法还有一个特点,就是很难找到逆向的规律
在日常的使用中,hash 算法常被用来对字符串进行压缩编码,将一段字符串转化成对应的数字或其他标志,以方便存储和比较。
开放地址法
将当前要存储的数字通过某种计算方式存放到“下一个”空位。
链地址法
每个下标对应的是一条不定长的链表。
ASCII 表中,有 128 种字符,每个字符都对应了 0~127 中的一个数字。
实际上,如果对于一个字符串,我们把字符串的每个字符转化成其对应的数字,那么就能得到一个 128 进制的数(每一位上的数字都在 0~127 中),将这个 128 进制的数转成对应的十进制,我们就把字符串和数字关联起来了。
当我们要比较两个字符串是否相同时,只要比较他们对应的十进制数是否相同即可,这就是哈希,字符串对应的十进制数就是它的哈希值
如果字符串很长,对应的十进制数太大怎么办?
取余,通常情况下是对一个大质数取余,来尽量降低两个不同的字符串对应相同的数的概率如何多次、快速求出子串的哈希值? 【可以先想想怎么求前缀的哈希值】
前缀哈希值可以记录下来,例如记 hash[i]表示前缀 i 的哈希值
可以利用两个前缀哈希值来求子串哈希值(前缀和思想)
求哈希值
题目描述
对于一个字符串,把字符串的每个字符转化成其对应的数字,可以得到一个128进制的数(每一位上的数字都在0~127中),再将这个128进制的数转成对应的十进制,就可以得到对应的哈希值。
输入一个字符串,请输出其哈希值对998244353取余的结果。
输入描述
输入一行,包含一个字符串。
输出描述
输出其哈希值对998244353取余的结果。
#include<bits/stdc++.h>
using namespace std;
string s;
long long mod=998244353;
long long has[100005];
int main(){
getline(cin,s);
has[0]=s[0];
for(int i=1;i<s.size();i++){
has[i]=(has[i-1]*128+s[i])%mod;
}
cout<<has[s.size()-1];
return 0;
}
求子串哈希值
int get(int l,int r){
return (has[r]-has[l]*pw[r-l+1]%mod+mod)%mod;
}
查字典
题目描述
你从现实世界穿越到异世界。这里的人讲一种难以理解的外语方言。幸运的是,你有找到一本字典来帮助你理解它们。
输入描述
若干组数据,每组数据:
第一行包含一个整数 n,表示字典条目数量。
然后是 n 行,每行代表一个字典条目,包含一个英语单词,后面是一个空格和一个外语单词。没有一个外语单词在词典中出现超过一次。
接下来一行包含一个整数 m,表示你需要翻译的信息条数。信息是一连串的外语单词,每行一个单词。
输入的每个词都是最多 20002000 个小写字母的非空序列。
全部数据满足:1≤n≤1000,1≤m≤1000
输出描述
输出是翻译成英文的信息,每行一个词,共 m 行。词典中没有的外国词应翻译为eh
。
消失的密文
题目描述
给你有 2626 个字母的密码表 S,S[i] 表示第 i 个字母经过密码表转变成的密码字符。(如 S[2]==‘c’
,表示字母 b
加密后变成 c
)
现在有一条密文,前一半为经过加密的字符,后一半为前一半加密前的字符。不过由于某些原因导致文末的部分内容消失了,你现在的任务是,恢复出最短的完整的密文。
输入描述
第一行只包含一个整数 T ,它是测试用例的数量。
每个测试用例包含两行。
每个测试用例的第一行是转换表 S 。S[i] 是第 i 个拉丁字母的加密字母。
第二行是截获的文本,其中有 n 个字母,你应该恢复。有可能该文本是完整的。
输出描述
对于每个测试用例,输出一行包含尽可能少的完整文本。