字符串哈希

进制哈希

BKDRHash哈希函数

字符串哈希:$\color{red}{构造一个数字使之唯一代表一个字符串}$。但是为了将映射关系一一对应,也就是,一个字符串代表一个数字,那么一个数字也对应一个字符串。
我们希望这一个映射是个单射,即保证任意的字符串对应的数字是唯一的,也就是不出现一个数字对应两个字符串等情况。

BKDRHash
BKDRHash是一种“进制哈希”,计算步骤非常简单。设定一个进制\(P\),需要计算一个字符串的哈希值时,把每个字符看作每个进制位上的一个数字,这个串转换为一个基于进制P的数,最后对\(M\)取余数,就得到了这个字符串的哈希值。

注意:
由于得到的哈希值都很大,不能直接映射到一个巨大的空间上,所以一般都需要限制空间。方法是取余,把得到的哈希值对一个设定的空间大小\(M\)取余数,以余数作为索引地址。当然这样做可能产生冲突问题。

编程时可以采用一种隐性取余的方法。取空间大小为\(M=2^{64}\),64是unsigned long long 型的长度,一个unsigned long long型的哈希值\(H\),当\(H>M\)时会自动溢出,等价于自动对\(M\)取余,这样可以避免低效的取余运算。

举例子:
以字符串“abc”为例,令进制\(P=131\),有以下两种方法。
\(1:\)把每个字符看作一个数字,即\(a=1,b=2,c=3....z=26\),然后把字符串的每位按进制\(P\)的权值相加得\('a' *131^2+'b'*131^1+'c'*131^0=17426\)

\(2.:\)把每个字符的ASCII码直接看成代表它的数字也可以,计算得\('a' *131^2+'b'*131^1+'c'*131^0=1677554\)

进制P常用的值有\(31、131、1313、13131、131313\)等,用这些数值可以有效避免碰撞。

模版题P3370 【模板】字符串哈希

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
#define all(v) v.begin(),v.end()
#define ull unsigned long long
ull bkdrhash(string s)
{
    ull p=131,h=0;//p为进制数,h为哈希值
    for(int i=0;i<s.size();i++)
    {
        h=h*p+s[i];
    }
    
    return h;
}


void solve()
{
    int n;
    cin>>n;
    set<int>se;
    while(n--)
    {
        string s;
        cin>>s;
        se.insert(bkdrhash(s));
    }
    cout<<se.size();
    
}





signed main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    int t=1;
    //cin>>t;
    while(t--) solve();
}

posted on 2024-07-26 13:06  swj2529411658  阅读(3)  评论(0编辑  收藏  举报

导航