哈希算法
这个算法可以在一个字符串中迅速判断两个字串是否相同。
根据朴素算法,我们直接将两个字串相比较,遇到不同的字符就break,这样的时间复杂度是o(n),而改进后的哈希算法的时间复杂度为o(1)。
下面我们来具体看看哈希算法(先假设字符串中皆为小写字母):
将字符串中的26个小写字母转换为数字,然后将每一个前缀的p进制的哈希值算出,通过比较对应的哈希值来确定两个字串是否相同。当然,p一般取131或13331,因为这样可以最大可能降低相同率,避免两个不同的字符串有相同的哈希值。由于字符串长度未知,哈希值可能会超过long long int的长度,但即使溢出也没有关系,溢出的值以long long int为例,会对2^64取模,对结果无太大关系。
以字符串str[]={a,b,c}为例:
先转化为数字:1 2 3;
为了方便运算,hash[0]=0;
计算每一个前缀的hash值(转化为131进制数):
hash[a]=h[0]^131+str[1]-‘a’+1=1;
hash[ab]=hash[a]^131+str[2]-‘a’+1=133;
hash[abc]=hash[ab]^131+str[3]-‘a’+1=17426;
此时,若是要知道字符串里两个字串是否相等则只要计算两个字串的哈希值是否相等即可。
如字符串s={a,b,c,a,b,c,g};
计算s[r]到s[l]之间的hash值(r>l):
hash[l–r]=hash[r]-hash[l-1]*131^(r-l+1);
131^(r-l+1)可以用一个数组存下。
两个步骤转化为代码:
在这里插入代码片
void f(int n)//n为字符串长度
{
hash[0]=0;
for(int i=1; i<n; i++)
{
hash[i]=hash[i-1]*131+s[i]-'a'+1;
a[i]=a[i-1]*131;
}
}
完整代码为
#include<stdio.h>
#include<string.h>
char s[1000010];
unsigned long long int hash[1000010],a[1000010]={1};
void f(int n)
{
hash[0]=0;
for(int i=1; i<n; i++)
{
hash[i]=hash[i-1]*131+s[i]-'a'+1;
a[i]=a[i-1]*131;
}
}
int main()
{
scanf("%s",s+1);//从s[1]开始存字符
int len,i;
len=strlen(s+1);
f(len);
unsigned long long int n,m,x,y,num1=0,num2=0;
scanf("%llu%llu%llu%llu",&n,&m,&x,&y);
num1=hash[m]-hash[n-1]*a[m-n+1];//两个字串的hash值的计算
num2=hash[y]-hash[x-1]*a[y-x+1];
if(num1==num2)
printf("Yes\n");
else printf("No\n");
return 0;
}
以上就是博主现在对哈希算法的理解。
来源:CSDN
作者:huang_c_c
链接:https://blog.csdn.net/huang_c_c/article/details/104134519