暑假acwing算法总结10:哈希

  • 1、散列表哈希
  • 1、拉链法
  • 就是一般的离散化,用邻接表存储数据
  • 先求大于离散化区间的最小质数,数学证明N是质数是冲突概率会降低
  • 代码
void insert(int x)//找到对应的邻接表每次头插就行
{
    int k=(x%N+N)%N;//确保余数为正数
    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;
}
  • 2、开放寻址法(蹲坑法)
  • 开一个一维数组如果取模后的x当前的坑位是空,则把他放到当前坑位,如果不为空则往后找直到不为空
  • 一般开两倍大小数组,为了留出空隙适合方便寻找的终止,也适合找坑的时候好找
  • 代码
int find(int x)
{
    int k=(x%N+N)%N;
    while(h[k]!=null&&h[k]!=x)
    {
        k++;
        if(k==N)k=0;
    }
    return k;
}
//插入操作
int k=find(x);
h[k]=x;//找空位
//查询操作
int k=find(x);
if(h[k]==x)cout<<"Yes"<<endl;
  • 2、字符串哈希
  • KMP的一生之敌,能做字符串匹配问题等几乎所有字符串问题
  • L~R的字符串哈希前缀和:h[l-1]=p(l-2) *p(l-3) *……p0
  • h[r]=p(r-1) *p(r-2) *……p0
  • 公式s[ r ] - s[ l - 1 ] * p[ r - l + 1 ]
  • 经验值P=131,mod=264,最大限度避免冲突,具体细节见代码
  • 代码
//abcdef
//h[1]=97
//h[2]=97*131+98
//h[3]=97*131*131+98*131+99
//h[4]=97*131*131*131+98*131*131+99*131+100
//......
//cd的哈希值等于99*131+100=h[4]-h[2]*131*131
#include<iostream>
using namespace std;
typedef unsigned long long ULL;//自动取余2^64,经验值
//最优权值131,13331,mod=2^64正好对应unsigned
const int N=100010,P=131;
int p[N],s[N];
ULL find(int l,int r)
{
    return s[r]-s[l-1]*p[r-l+1];
}
int main()
{
    int n,m;cin>>n>>m;
    char a[N];
    scanf("%s",a+1);
    p[0]=1;
    for(int i=1;i<=n;i++)
    {
        p[i]=p[i-1]*P;
        s[i]=s[i-1]*P+a[i];
    }
    while(m--)
    {
        int l1,r1,l2,r2;
        cin>>l1>>r1>>l2>>r2;
        if(find(l1,r1)==find(l2,r2))puts("Yes");
        else puts("No");
    }
    return 0;
}
//2021-07-13/01:53
  • 2021-07-13写于南宁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值