解决冲突的两种方式:开放寻址法和拉链法
使用拉链法,更多的是对于链表的熟练程度,链表插入元素+查找元素
注意,这个模一般要取质数
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100003;
int h[N],e[N],ne[N],idx;
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;
}
int main()
{
memset(h, -1, sizeof h);
int T;cin>>T;
while(T--)
{
char op;
int x;
cin>>op>>x;
if(op=='I')insert(x);
if(op=='Q')
{
if(find(x))cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
return 0;
}
开放寻址法
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 2e5+3;
const int mark=0x3f3f3f3f;
int h[N];
int find(int x)
{
int k=(x%N+N)%N;
while(h[k]!=mark&&h[k]!=x)//找
{
k++;
if(k==N)k=0;
}
return k;
}
int main()
{
memset(h, 0x3f, sizeof h);
int T;cin>>T;
while(T--)
{
char op;
int x;
cin>>op>>x;
int pos=find(x);
if(op=='I')h[pos]=x;
if(op=='Q')
{
if(h[pos]!=mark)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
return 0;
}
STL大法
#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_set>
using namespace std;
const int N = 200003, null = 0x3f3f3f3f;
int n;
int main()
{
scanf("%d", &n);
unordered_set<int> hash;
while (n -- )
{
char op[2];
int x;
scanf("%s%d", op, &x);
if (op[0] == 'I') hash.insert(x);
else
{
if (!hash.count(x)) puts("No");
else puts("Yes");
}
}
return 0;
}
字符串哈希
关键点1:hash值为return h[r]-h[l-1]*p[r-l+1];
关键点2:初始化
关键点3:ULL 和P=13331或者P=131
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
const int P=13331;
typedef unsigned long long ULL;
char str[N];
ULL h[N],p[N];
int n,m;
ULL get(int l,int r)
{
return h[r]-h[l-1]*p[r-l+1];
}
int main()
{
cin>>n>>m;
cin>>str+1;
p[0]=1;
for(int i=1;i<=n;i++)
{
p[i]=p[i-1]*P;
h[i]=h[i-1]*P+str[i];
}
while (m -- )
{
int l1,l2,r1,r2;
cin>>l1>>r1>>l2>>r2;
if(get(l1,r1)==get(l2,r2))cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
洛谷模板
主要是这些哈希函数的经验写法
int prime=233317;
ull mod=212370440130137957ll;//2的64次方等
ull gethash(char s[])
{
int len=strlen(s);//长度
ull ans=0;
for (int i=0;i<len;i++)
ans=(ans*P+(ull)s[i])%mod+prime;
return ans;
}
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
ull P=131;//进制,经验值13331 131
ull a[10010];
char str[10010];
int n,ans=1;
int prime=233317;
ull mod=212370440130137957ll;//2的64次方等
ull gethash(char s[])
{
int len=strlen(s);//长度
ull ans=0;
for (int i=0;i<len;i++)
ans=(ans*P+(ull)s[i])%mod+prime;
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
cin>>str;
a[i]=gethash(str);
}
sort(a+1,a+n+1);
for(int i=1;i<n;i++)
{
if(a[i]!=a[i+1])
ans++;
}
printf("%d",ans);
return 0;
}
快读(在写一道简单的哈希题目中碰到的)
int read(){
int w=1,q=0;
char ch=' ';
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')q=q*10+ch-'0',ch=getchar();
return w*q;
}