算法 字符串Hash

解决问题:

      字符串hash主要应用在:在长度为n的主串S中匹配长度为m的匹配串T,返回起始位置。

Hash的目的:

      通过字符串Hash函数把一个任意长度的字符串映射成一个非负整数,并且其冲突概率为零。

具体方法:

        取一固定值P,把字符串看作P进制数,并分配一个大于0的数值,代表每种字符。一般来说,我们分配的数值都远小于P。取一固定值M,求出P进制数对M的余数,作为该字符串的Hash值。
      一般来说,我们取P = 131 或 13331,此时Hash值产生冲突的概率极低,只要Hash值相同,我们就可以认为原字符串是相等的。通常我们取M = 2 ^ 64,即直接使用unsigned long long 类型储存这个Hash值,在计算时不处理算数溢出问题,产生的溢出相当于自动对 2 ^ 64取模。

具体运算:

      记字符串S的Hash值为H(S),那么在S后添加一个字符c构成的新字符串的 S + c 的Hash值H(S + c) = (H(S) * p + val[c]) mod M。val[c]为字符c的代表数值。
      同理去除字符串首位(最高位)H[S] = H[c + S] - val[c] * p ^ length(S);

不足之处:

      对于Hash值在0 ~ n之间均匀分布的Hash函数,出现不同字符串Hash值相等的期望步骤是O(sqrt(n)),在可以当作选取Hash函数的参考。
      同时为了及降低出现相同Hash值的概率,可以采取双哈希来降低出现相同Hash值的概率,只有两个Hash值相等才认定字符串匹配。如取:10 ^ 9 + 7 与 10 ^ 9 + 9。

代码举例:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ULL;
ULL base = 131;
int main(){
	string s;
	cin>>s;
	ULL res = 0;
	for(int i = 0; i < s.length(); i++){
		res = res * base + s[i] - 'a' + 1;
	}
	cout<<res;
}

参考:
leetcode-huwt
字符串hash-二喵君

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值