加载中...

哈希表

\[哈希表 \begin{cases} 存储结构 \begin{cases} 开放寻址法 \\[2ex] 拉链法 \\[2ex] \end{cases} \\[3ex] 字符串哈希方式\\[3ex] \end{cases} \]



一般哈希

开放寻址法
//开放寻址法模板

const int N=(数据范围的2~3倍,质数),null=(数据范围外的数,常用0x3f3f3f3f);
int h[N];
memset(h,null,sizeof h);

//如果x在哈希表中,返回x的下标;如果x不在哈希表中,返回x应该插入的位置
int find (int x)
{
    int t=(x%N+N)%N;
    while(h[t]!=null&&h[t]!=x)
    {
        t++;
        if(t==N)t=0;
    }
    return t;
}

拉链法
//拉链法模板

int h[N],e[N],ne[N],idx;
memset(h,-1,sizeof h);	//将单数组每个点的指针初始化为空指针-1

//向哈希表中插入一个数
void insert (int x)
{
    int k=(x%N+N)%N;  //保证k为非负数
    e[idx]=x;
    ne[idx]=h[k];
    h[k]=idx++;
}

//在哈希表中查询某个数是否存在
bool find (int x)
{
    int k=(x%N+N)%N;
    for(int i=h[k];i!=-1;i=ne[i])
        if(e[i]==x)return true;
    return false;
}



字符串哈希

核心思想: 将字符串看成 p 进制数, p 的经验值是 13113331 , 取这两个值冲突概率低

小技巧: 取模的数用 \(2^{64}\) , 这样直接用 unsigned long long 存储, 溢出的结果就是取模的结果


//字符串哈希模板

const int p=131;
unsigned long long h[N],p[N];
//h[k]存储字符串前k个字母的哈希值,p[k]存储(p^k)%(2^64)

//初始化
p[0]=1;
for(int i=1;i<=n;i++)
{
    h[i]=h[i-1]*p+str[i];
    p[i]=p[i-1]*p;
}

//计算子串str[l~r]的哈希值
unsigned long long get (int l,int r)
{
    return h[r]-h[l-1]*p[r-l+1];
}


posted @ 2023-04-29 19:11  邪童  阅读(24)  评论(0编辑  收藏  举报