关于哈希的总结

注:
1. 本文章主要为了说明关于哈希函数的选取,但不说明为什么要这么选。
2. 只针对做题的哈希及哈希表的总结,不是工业加密的那个哈希。。
主要选取以下题目:
poj1840 poj3640 poj3349 poj2002 poj1200 poj2503 poj1496 poj3274 poj1077

哈希的作用我觉得就是判重和查找,其实是一个意思。如果题目要求判断数组,字符串,一个数,等等是否出现过,或者是否和另一个数组,字符串相等。这时候我们就可以利用哈希的特性,将其转换成一个数字,然后进行判断。

考哈希的题都有以上特点,那时只需用一个哈希函数转换一下就ok了,那么该如何转换呢?

  • 数组的转换
int getkey(int *v,int k)
{
       int i,p=0;
       for(i=1; i<k; i++)
              p=((p<<2)+(v[i]>>4))^(v[i]<<10);
       p = p%prime;
       if(p<0)    p=p+prime;
       return p;
}
  • 字符串的转换(cf 835D(可参考我的另一篇博客))
unsigned long long p[maxn+10];//maxn为字符串的最长长度
unsigned long long S[maxn+10];
void init()
{
    p[0]=1;
    for(int i=1;i<=maxn;i++)
        p[i]=p[i-1]*hashsize;
    for(int i=1;i<=len;i++)
        S[i]=S[i-1]*hashsize+a[i-1];

}

unsigned long long HS(int l,int r)
{
    if(l==r)return a[l];
    l++,r++;
    return S[r]-S[l-1]*p[r-l+1];
}
  • 从1到n的全排列
    这个专业术语叫做康拓展开,但我感觉和hash如出一辙,将一个排列转换成一个0-n!-1的一个数。
int fact[10];                                           //fact[i] = i!
fact[0] = 1;
for(int i = 1; i < 9; ++i) fact[i] = fact[i-1]*i;

int kt(int s[], int n) {                                //n个数的排列s[0,n-1]
    int ans = 0, cnt = 0;                               //返回其在全排列中的位置-1
    for(int i = 0; i < n; ++i) {
        cnt = 0;                                        //cnt为在i后面出现的小于s[i]的数的个数
        for(int j = i+1; j < n; ++j) if(s[j] < s[i]) ++cnt;
        ans += cnt*fact[n-i-1];
    }
    return ans;
}

结语: 博主其实对哈希的理解非常浅薄,如果有更好的哈希函数,希望能和读者一起探讨,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值