字符串Hash入门
字符串Hash可以通俗的理解为,把一个字符串转换为一个整数。
如果我们通过某种方法,将字符串转换为一个整数,就可以便的确定某个字符串是否重复出现过,这是最简单的字符串Hash应用情景了。
当然也不难想到,如果有不同的两个字符串同时Hash到一个整数,这样就比较麻烦了。我们希望这个映射是一个单射,所以问题就是如何构造这个Hash函数,使得他们成为一个单射。不用担心,接下来的内容正要讲解。
Hash方法
给定一个字符串 ,对字母x,我们规定 。 (当然也可以直接用 的 值)
自然溢出方法
Hash公式
unsigned long long Hash[n]
利用unsigned long long的范围自然溢出,相当于自动对 取模
单Hash方法
Hash公式
其中 和 均为质数,且有 。
对于此种Hash方法,将p和mod尽量取大即可,这种情况下,冲突的概率是很低的。
举例
如取
,对字符串
进行Hash
hash[0] = 1
hash[1] = (hash[0] * 13 + 2) % 101 = 15
hash[2] = (hash[1] * 13 + 3) % 101 = 97
这样,我们就认为字符串 当做97,即97就是 的hash值。
双Hash方法
将一个字符串用不同的 hash两次,将这两个结果用一个二元组表示,作为Hash结果。
Hash公式
hash结果为
这种Hash很安全。
获取子串的Hash
如果我们求出一个串的Hash,就可以
求解其子串的Hash值。
我们先以一个具体的例子来理解。
例子
假设有一 的字符串,设 为第 个字符,其中 。
根据定义分别求出
现在我们想求 的hash值,不难得出为 ,并且从上面观察,如果看 并将结果种带有 系数的项全部消掉,就是所求。但是由于 的阶数,不能直接消掉,所以问题就转化成,将 乘一个关于 的系数,在做差的时候将多余项消除,从而得到结果。
不难发现,对应项系数只差一个 ,而4 - 3 + 1 = 2(待求hash子串下标相减再加一),这样就不难推导出来此例题的求解式子。
至此,通过对上例的归纳,可以得出如下的公式。
公式
若已知一个 的字符串的hash值, ,其子串 对应的hash值为:
考虑到 每次对 取模,进一步得到下面的式子:
看起来这个式子人畜无害,但是对于取模运算要谨慎再谨慎,注意到括号里面是减法,即有可能是负数,故做如下的修正:
至此得到求子串hash值公式。
值得一提的是,如果需要反复对子串求解hash值,预处理 的 次方效果更佳。
字符串Hash的应用
题型一
描述
问题:给两个字符串S1,S2,求S2是否是S1的子串,并求S2在S1中出现的次数
数据范围:1=<|S1|,|S2|<=10000
解法
求出S1和S2的Hash值,并且 的求解出S1所有子串的Hash值,放入map中,查询即可。复杂度
题型二
描述
问题:给N个单词串,和一个文章串,求每个单词串是否是文章串的子串,并求每个单词在文章中出现的次数。
数据范围:文章串长度:[1,10^5],N个单词串总长:[1,10^6]
解法
设单词串总长为 ,文章串总长为 。
此题和第一题做法相同。复杂度
题型三
描述
问题:给两个字符串S1,S2,求它们的最长公共子串的长度。
数据范围:1=<|S1|,|S2|<=10^5
解法
将S1的每一个子串都hash成一个整数
将S2的每一个子串都hash成一个整数
两堆整数,相同的配对,并且找到所表示的字符串长度最大的即可。
复杂度:
PS:为觉得开数组不保险,所以上面的题一和题二都用的map存,这里我也不知道能不能实现 的存储和查询。
题型四
描述
问题:给一个字符串S,求S的最长回文子串。
比如abcbbabbc的最长回文子串是cbbabbc,bbabb也是回文串,但不是最长的
数据范围: 1=<|S|<=10^5
解法
先求子串长度位奇数的,再求偶数的。枚举回文子串的中心位置,然后二分子串的长度,直到找到一个该位置的最长回文子串,不断维护长度最大值即可。
复杂度:
Hash素数的选取
为了防止冲突,要选择合适的素数,像1e9+7,1e9+9的一些素数,出题人一般会卡一下下,所以尽量选择其他的素数,防止被卡。下面是一些可供选择的素数。
上界和下界指的是离素数最近的
的值。
lwr(下界) | upr(上界) | %err(冲突率) | prime(素数) |
---|---|---|---|
10.416667 | 53 | ||
1.0416670 | 97 | ||
0.520833 | 193 | ||
1.302083 | 389 | ||
0.130208 | 769 | ||
0.455729 | 1543 | ||
0.227865 | 3079 | ||
0.113932 | 6151 | ||
0.008138 | 12289 | ||
0.069173 | 24593 | ||
0.010173 | 49157 | ||
0.013224 | 98317 | ||
0.002543 | 196613 | ||
0.006358 | 393241 | ||
0.000128 | 786433 | ||
0.000318 | 1572869 | ||
0.000350 | 3145739 | ||
0.000207 | 6291469 | ||
0.000040 | 12582917 | ||
0.000075 | 25165843 | ||
0.000010 | 50331653 | ||
0.000023 | 100663319 | ||
0.000009 | 201326611 | ||
0.000001 | 402653189 | ||
0.000011 | 805306457 | ||
0.000000 | 1610612741 |