【算法学习】字符串Hash入门

字符串Hash入门

字符串Hash可以通俗的理解为,把一个字符串转换为一个整数

如果我们通过某种方法,将字符串转换为一个整数,就可以便的确定某个字符串是否重复出现过,这是最简单的字符串Hash应用情景了。

当然也不难想到,如果有不同的两个字符串同时Hash到一个整数,这样就比较麻烦了。我们希望这个映射是一个单射,所以问题就是如何构造这个Hash函数,使得他们成为一个单射。不用担心,接下来的内容正要讲解。

Hash方法

给定一个字符串 S = s 1 s 2 s 3 . . s n S = s_1s_2s_3..s_n S=s1s2s3..sn,对字母x,我们规定 i d x ( x ) = x − ′ a ′ + 1 idx(x) = x - 'a' +1 idx(x)=xa+1。 (当然也可以直接用 s i s_i si A S C I I ASCII ASCII值)

自然溢出方法

Hash公式

unsigned long long Hash[n]

h a s h [ i ] = h a s h [ i − 1 ] ∗ p + i d ( s [ i ] ) hash[i] = hash[i-1] * p + id(s[i]) hash[i]=hash[i1]p+id(s[i])

利用unsigned long long的范围自然溢出,相当于自动对 2 64 − 1 2^{64} -1 2641取模

单Hash方法

Hash公式

h a s h [ i ] = ( h a s h [ i − 1 ] ) ∗ p + i d x ( s [ i ] )   %   m o d hash[i] = (hash[i-1]) * p + idx(s[i]) \ \% \ mod hash[i]=(hash[i1])p+idx(s[i]) % mod

其中 p p p m o d mod mod均为质数,且有 p < m o d p < mod p<mod

对于此种Hash方法,将p和mod尽量取大即可,这种情况下,冲突的概率是很低的。

举例

如取 p = 13 , m o d = 101 p = 13, mod = 101 p=13,mod=101,对字符串 a b c abc abc进行Hash
hash[0] = 1
hash[1] = (hash[0] * 13 + 2) % 101 = 15
hash[2] = (hash[1] * 13 + 3) % 101 = 97

这样,我们就认为字符串 a b c abc abc当做97,即97就是 a b c abc abc 的hash值。

双Hash方法

将一个字符串用不同的 m o d mod mod hash两次,将这两个结果用一个二元组表示,作为Hash结果。

Hash公式

h a s h 1 [ i ] = ( h a s h 1 [ i − 1 ] ) ∗ p + i d x ( s [ i ] )   %   m o d 1 hash1[i] = (hash1[i-1]) * p + idx(s[i]) \ \% \ mod1 hash1[i]=(hash1[i1])p+idx(s[i]) % mod1

h a s h 2 [ i ] = ( h a s h 2 [ i − 1 ] ) ∗ p + i d x ( s [ i ] )   %   m o d 2 hash2[i] = (hash2[i-1]) * p + idx(s[i]) \ \% \ mod2 hash2[i]=(hash2[i1])p+idx(s[i]) % mod2

hash结果为 < h a s h 1 [ n ] , h a s h 2 [ n ] > <hash1[n],hash2[n]> <hash1[n],h

评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值