哈希算法

本文介绍了哈希算法如何用于快速比较两个字符串的相同性,从朴素算法的O(n)时间复杂度提升到O(1)。通过将字母映射为数字并计算131或13331进制的哈希值,可以有效降低碰撞概率。以实例解释了计算字符串前缀哈希值的方法,并展示了如何用代码实现这一过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

哈希算法

这个算法可以在一个字符串中迅速判断两个字串是否相同

根据朴素算法,我们直接将两个字串相比较,遇到不同的字符就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;
}

以上就是博主现在对哈希算法的理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值