字符串Hash
字符串hash就是把一个字符串变成一个整数
当两个字符串相同时,它们通过hash计算后得到的整数相同,当两个字符串不同时,它们的数字就不同。
Hash公式
首先设一个进制数base,和一个取模数mod
给定一个字符串S
id(x)=x - ‘a’ + 1
*hash[ i ] =hash[ i -1 ] base + id(s[ i ])
hash冲突
比如orzc的哈希值为233,orzhjw的哈希值也为233
而这两个字符串显然不相同,这就叫hash冲突。
单hash方法
就是一个取模运算,只进行一次hash运算。公式如下:
*hash[i]=(hash[i-1]base+id(s[i]))%mod
单哈希的hash冲突概率很低
例:取base=13,mod=101, 对字符串abc进行hash
hash[0] = 1
hash[1] = (hash[0] * base +id(s[1]) % mod =15
hash[2] = (hash[1] * base + id[s[2]) % mod = 97
所以当base=13,mod=101时,可以把abc当作97,**即abc的hash值为97 **
代码如下:
int n=strlen(s+1),base=13,mod=101;
int hash[1001],id[1001];
hash[0]=1;
for(int i=1;i<n;i++)
{
id[i]=s[i+1]-'a'+1;
hash[i]=(hash[i-1]*base+id[i])%mod;
}
printf("hash值为%d\n",hash[n-1]);
双hash方法
进行两次hash运算,两次hash进行比较,避免hash冲突
代码如下:
int n=strlen(s+1);
int base1=131,mod1=11345646;
int base2=131,mod2=12341654;
int hash1[1001],id1[1001];
int hash2[1001],id2[1001];
hash[0]=1;
for(int i=1;i<n;i++)
{
id1[i]=s[i+1]-'a'+1;
hash1[i]=(hash1[i-1]*base1+id1[i])%mod1;
id2[i]=s[i+1]-'a'+1;
hash2[i]=(hash2[i-1]*base2+id2[i])%mod2;
}
if(hash1[n-1]==hash2[n-1])
https://www.acwing.com/problem/content/description/140/
兔子与兔子,求两个子串是否相同
代码如下:
#include<stdio.h>
#include<string.h>
#define N 1000001
char s[N];
unsigned long long int hash[N],str[N];
unsigned long long int fun(int x,int y)
{
return hash[y]-hash[x-1]*str[y-x+1];
}
int main()
{
int i,j;
while(~scanf("%s",s+1))
{
int m,n;
scanf("%d",&m);
n=strlen(s+1);
str[0]=1;
for(i=1;i<=n;i++)
{
hash[i]=hash[i-1]*131+s[i]-'a'+1;
str[i]=str[i-1]*131;
}
while(m--)
{
int l1,l2,r1,r2;
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
if(fun(l1,r1)==fun(l2,r2))
printf("Yes\n");
else
printf("No\n");
}
}
return 0;
}
来源:CSDN
作者:Whitegost
链接:https://blog.csdn.net/Whitegost/article/details/104137868