首页 > 其他分享 >「杂谈」字符串 Hash

「杂谈」字符串 Hash

时间:2024-01-14 21:27:21浏览次数:25  
标签:Hash 2q 多项式 杂谈 底数 模数 字符串

我们常用的字符串 Hash 形如:

\[f(s) = \sum_{i = 1}^{n} s_i \times b^{n - i} \bmod p \]

但是经常有人写出不正确的 Hash。举例说明,以下 Hash 是不正确的:

  1. 自然溢出 Hash。
  2. 固定底数和模数,模数是 \(2^{64}\) 级别的 Hash。
  3. 固定底数和模数,模数数 \(2^{32}\) 级别的双 Hash。

具体的 Hack 方法见 CF 上的一篇文章

还有一种正确性存疑的 Hash:

  1. 固定模数,随机底数,但是模数减 \(1\) 有大量小质因数的 Hash。

下面给出一种正确的 Hash:

固定模数,随机底数,模数在 \(2^{32}\) 级别,且模数减 \(1\) 的 \(1 \over 2\) 是质数的双 Hash。

这样做为什么对呢?考虑两个等长字符串 \(s,t\),\(f(s) = f(t)\) 相当于这样一件事情成立:

\[\sum_{i = 1}^n (s_i - t_i) \times b^{n - i} \equiv 0 \pmod p \]

这是一个关于 \(b\) 的至多 \(n - 1\) 次非零多项式。因为 \(p\) 是质数,所以该多项式在 \(\mathbb{F}_M\) 域上的根至多有 \(n - 1\) 个,因此 Hash 碰撞的概率不超过 \({n - 1} \over p\)。双 Hash 即可保证正确性。

那为什么 \(p - 1\) 不能有很多小质因数呢?因为如果 \(b\) 模 \(p\) 的阶很小,那么高次项会自动取模,那么我们可以直接构造出一个零多项式,因此正确性是无法保证的。不过,如果 \(p - 1 = 2q\),那么 \(b\) 模 \(p\) 的阶只能是 \(1, 2, q, 2q\)。\(q\) 和 \(2q\) 已经足够大(远大于 \(n\)),而阶为 \(1\) 的只有 \(1\),阶为 \(2\) 的只有 \(p - 1\),因此我们令 \(b\) 在 \([2, p - 2]\) 中均匀随机即可。

不过合适的 \(p\) 确实不好找。这里讲一组好记的:\(10^9 + 7\) 和 \(10^9 + 787\)。

标签:Hash,2q,多项式,杂谈,底数,模数,字符串
From: https://www.cnblogs.com/ClHg2/p/17964195

相关文章

  • (△△△)开发一个坐标计算工具, A表示向左移动,D表示向右移动,W表示向上移动,S表示向下移动
    描述开发一个坐标计算工具,A表示向左移动,D表示向右移动,W表示向上移动,S表示向下移动。从(0,0)点开始移动,从输入字符串里面读取一些坐标,并将最终输入结果输出到输出文件里面。输入:合法坐标为A(或者D或者W或者S)+数字(两位以内)坐标之间以;分隔。非法坐标点需要进行丢弃。如AA10;......
  • string 字符串用法C++
    substr() c_str() size()/length()  empty() clear() #include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<vector>usingnamespacestd;intmain(){stringa="abc";......
  • 如何把将字符串中的数字转换成数字
    主要采用的是库函数的方法,isdigit,stoi.isdigit可以判断单个字符是否是数字,stoi可以将多个字符(多位数,复数)转换成数字。判断数字可以结合isdigit给出对应的函数。点击查看代码boolisNumber(conststd::string&token){//Checkifthetokenisanumber(posit......
  • [刷题班] LeetCode344. 反转字符串
    题目描述思路:左右指针方法一:classSolution{publicvoidreverseString(char[]s){intleft=0,right=s.length-1;while(left<right){chartemp=s[left];s[left]=s[right];s[right]=temp;......
  • 重复的子字符串
    最开始想的是暴力解法,但总是超时,后来问了chatgp,可以通过用substr来缩短时间。勉强通过,耗时还是很大。点击查看代码classSolution{public:boolrepeatedSubstringPattern(strings){intcount=1;stringtemp;while(count<=s.size()/2){temp=s.substr(0,count);......
  • 反转字符串中的单词
    最开始我是用笨方法解决的,就是新建了一个字符串,不断增加限制条件来实现的。点击查看代码classSolution{public:stringreverseWords(strings){stringtemp;stringcnt;intsz=s.size();intj=0;for(inti=sz-1;i>=0;i--){if(s[i]!=''){temp.push......
  • C++实现文件内查找字符串
    实现概要:读取放入buf后查找匹配的第一个字符然后使用seek()移动文件指针,peek()查看剩余的字符是否匹配如果剩余的字符匹配把该字符串在文件中的位置push进一个vector<int>中再继续查看剩余的文件内容//str2.cpp--capacity()andreserve()#include<iostream>......
  • 【教3妹学编程-算法题】构造限制重复的字符串
    3妹:“太阳当空照,花儿对我笑,小鸟说早早早,你为什么背上炸药包”2哥:3妹,什么事呀这么开森。3妹:2哥你看今天的天气多好啊,最近一周都是大晴天,艳阳高照2哥:是啊,天气不冷不热的,很适合生活3妹:据说南方的小土豆都跑到北方滑雪了,哈哈哈哈2哥:泼水成冰好玩是好玩,但是一定要注意防寒哦,看新闻都有......
  • SQL SERVER日期时间转字符串
    SQLSERVER日期时间转字符串一、sql server日期时间函数--当前系统日期、时间selectgetdate()--dateadd在向指定日期加上一段时间的基础上,返回新的datetime值--例如:向日期加上2天selectdateadd(day,2,'2004-10-15')--返回:2004-10-1700:00:00.000--datediff......
  • 【教3妹学编程-算法题】统计出现过一次的公共字符串
    3妹:哈哈哈哈哈哈,太搞笑了~呵呵呵呵呵呵2哥:3妹干嘛呢,笑的这么魔性!3妹:在看王牌对王牌,老搞笑了2哥:这季好像没有贾玲吧。3妹:是啊,听说贾玲去导电影了,还狂瘦了100斤呢,哎,我也该减减肥了。2哥:切,你每隔几天就会说要减肥,也没见你减啊3妹:不吃饱哪有力气减肥,我每天还要刷题、找工作,多辛苦啊......