哈希

值冲突解决方法一

(了解即可)

在插入发生冲突时,往后找第一个空着的位置,将值插入;

相应的在值查询时,不仅要查询哈希函数对应的位置,还要依次比较连续的非空的哈希表中的值

const int modnum = N;
int HashTable[modnum];
int Hash(int x) { return x % modnum; }
//插入新值
void Insert(int x) {
    int addr = Hash(x);
    while (HashTable[addr] != NULL)
        addr = (addr + 1) % modnum;
    HashTable[addr] = x;
}
//查找元素
bool IsExist(int x) {
    int addr = Hash(x);
    while (HashTable[addr] != NULL) {
        if (HashTable[addr] == x)
            return true;
        addr = (addr + 1) % modnum;
    }
    return false;
}

值冲突解决方法二:

在每一个存哈希值的地方都开一个vector

一般在手写哈希函数的时候,会要求Hash(x)=x%pHash(x)=x\%p中的p为素数,如9999971,9999973

字符串哈希

对于s=s1s2s3sn,siϵazs=s_{1}s_{2}s_{3}…s_{n}, s_{i} \epsilon{a…z}

它的哈希函数为:

对于Hash(s)=(i=1ncibaseni)modpHash(s)=(\sum_{i=1}^{n}c_{i}*base^{n-i})modp

base是一个由你指定的数,一般是一个大于等于字符集中字符数量(cic_{i}的最大值)的素数,比如这里可以取base=31;

实际操作时常考虑双哈希

还可以利用类似前缀和的思想,快速得到任意一段子串的哈希值

用数组a记录下我们计算Hash(c)的中间过程,a[1]=Hash(c1),a[2]=Hash(c1c2)a[1]=Hash(c_{1}),a[2]=Hash(c_{1}c_{2})……

即有a[i]=Hash(s1s2sn)a[i]=Hash(s_{1}s_{2}…s_{n})

那么字符串s的任意子串sl,r=slsl+1srs_{l,r}=s_{l}s_{l+1}…s_{r}的哈希值为:

对于Hash(sl.r)=(a[r]a[l1]baserl+1)modpHash(s_{l.r})=(a[r]-a[l-1]*base^{r-l+1})modp

unordered_map

$$unordered_map<K,V>hash_table

例题:小蜗的疑问

现在给你两个字符串a和b,a和b都由小写字母构成。

小蜗想知道字符串b在a中出现了几次(出现位置可以重叠)。

单哈希:

双哈希:

Last updated