哈希表

哈希表

引入:

如果我们要存放一堆数据,但是这些数据很大,直接用 \(vis\) 之类的不能忍一下。

而且要求尽量做到 \(O(1)\) 查询

那么就引入了哈希表。

定义:

散列表(又称哈希表,\(Hash Table\))是一种常用数据结构。它按照哈希特征分类存放,能够实现插入 \(O(1)\),查询均摊较低,几乎可做到 \(O(1)\) ,最差 \(O(n)\)

实现过程:

定义数组:

int val[N],edge[N],nxt[N],head[N],tot;
//val表示该点对应的值,edge表示该点对应的值的权值,查询时给出。

插入:

插入对应的值和权值,在链表上查询有无点对应的权值是给定的值,如果没有就新建节点。

过程就是链表的建立过程。

void insert(int k,int c){
    int x=k%mod;
    for(int i=head[x];i;i=nxt[i]){
        if(val[i]==k){
            edge[i]=c;//这里情况比较多变 
            return; 
        } 
    }
    val[++tot]=k; edge[tot]=c;
    nxt[tot]=head[x]; head[x]=tot;
}

查询:

通过链表搜索数据,返回值即可。

int calc(int k){
    int x=k%mod;
    for(int i=head[x];i;i=nxt[i]){
        if(val[i]==k) return edge[i];
    }
    return 0;
}

例题:

题意:

给定两个集合(数组) \(a,b\),求有多少数对 \((i,j)\) 满足 \(a_i \otimes b_i\) 在二进制下包含两个 \(1\)

分析:

暴力就是 \(O(n^2)\) ,随便写。

二进制下包含两个 \(1\) ,表示这两个数二进制下只有两位不同。

\(a_i \otimes (2^x)=b_j \otimes (2^y)\) ,即恰好两位不一样,那么就有了一个满足的数对。

我们用 哈希表 记录每一个 \(a_i \otimes 2^{0,1,2...29}\)

为了防止重复,先判断哈希表中有没有存在 \(b_{[1,m]} \otimes 2^j\) 的值,然后再插入 \(a_{[1,n]} \otimes 2^j\) 即可。

插入时,记得权值要为加和,而不是直接等于。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e7+40;
const int mod=1e7+19;
int n,m;
int a[N],b[N],ans;
int val[N],edge[N],nxt[N],head[N],tot;
void insert(int k,int c){
    int x=k%mod;
    for(int i=head[x];i;i=nxt[i]){
        if(val[i]==k){
            edge[i]+=c;//这里权值是+=
            return; 
        } 
    }
    val[++tot]=k; edge[tot]=c;
    nxt[tot]=head[x]; head[x]=tot;
     
}
int calc(int k){
    int x=k%mod;
    for(int i=head[x];i;i=nxt[i]){
        if(val[i]==k) return edge[i];
    }
    return 0;
}

int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=m;i++) scanf("%d",&b[i]);
    for(int i=0;i<=29;i++){
        int k=1<<i;
        for(int j=1;j<=m;j++) ans+=calc(b[j]^k);
        for(int j=1;j<=n;j++) insert(a[j]^k,1);
    }
    printf("%d\n",ans);
    system("pause");
    return 0;
}

注意事项:

哈希表一般对于查询时值太大很好用,但是有风险性。

开数组时,尽量不要开太大,避免出锅直接炸内存。

常用的模数:\(19260817\)(危险) , \(1e7+19\)

posted @ 2021-09-25 20:19  Evitagen  阅读(194)  评论(0编辑  收藏  举报