字符串哈希(BKDR_hash)

本文深入探讨了字符串哈希算法的原理与应用,通过将不同字符串转换为唯一整数,实现高效判断字符串是否相等的功能。文章介绍了哈希算法的基本概念,如何避免冲突,以及通过取模和选择合适基数来优化哈希值计算。通过具体代码示例,展示了BKDR哈希函数的实现过程,包括字符串转换、哈希值计算和子串匹配的方法。

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

当我们要判断两个字符是否相等时,如S1="abc",S2=“abb”。如果我们从头到尾逐个比较,则时间复杂度为O(m)。
这里我们就要用到字符串哈希来降到O(1)。

字符串哈希入门

说得通俗一点,字符串哈希实质上就是把每个不同的字符串转成不同的整数。

为什么会有这样的需要呢?很明显,存储一个超长的字符串和存储一个超大但是能存的下的整数,后者所占的空间会少的多,但主要还是为了方便判断一个字符串是否出现过,这是最基础的部分。

当然也很容易想到,如果有不同的字符串转成同一个整数,那么区分功能就基本废掉 ,所以我们需要一个算法把每个字符串转成唯一的整数。所以字符串哈希算法就应运而生,哈希算法的难点也就在于如何构造一个合适的Hash函数来满足我们的需求。

单哈希法

hash函数要做到一一对应
 hash函数要做到一一对应
如果我们按这个转换规则,得到的hash_code值会很大很大,计算机根本存不下。这个时候就需要我们来取模了。 但取模的数不能乱取,不然会造成冲突(即两个字符串不相等,但取模后结果相同)。
这里我们用到一个小技巧,就是unsigned long long 如果溢出以后,它会自动帮你%2^64。
我们还可以从X(表示转换为X进制)来降低冲突。根据计算机科学家概率的方式来统计,发现X取:131,1331,13331… 它的冲突率是最小的。

冲突解决

在这里插入图片描述
在这里插入图片描述

代码块

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
const ll mod=1e9+7;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int N=1000010;
const int X=13331;
char T[N];
char S[N];
ull h[N],x[N],hs[N];
vector<ull>v;
void BKDR_hash(char s[])
{
    h[0]=s[0];
    x[0]=1;
    int ln=strlen(s);
    for(int i=1;i<ln;i++)
    {
        h[i]=h[i-1]*X+s[i];
        x[i]=x[i-1]*X;
    }
}
ull get_hash(int left,int right)
{
    if(!left)
        return h[right];
    else
        return h[right]-h[left-1]*x[right-left+1];
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>T;
    BKDR_hash(T);
    cin>>S;
    ull hs2=0;
    for(int i=0;i<strlen(S);i++)
        hs2=hs2*X+S[i];
    for(int i=0;i<strlen(T);i++)
        cout<<get_hash(i,min(strlen(T)-1,i+strlen(S)-1))<<" ";
    cout<<endl;
    cout<<hs2<<endl;
    //检测S串是否是T串的子串    通过对比hash_code值
}

运行截图
运行截图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值