-
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,最大限度避免冲突,具体细节见代码
- 代码
#include<iostream>
using namespace std;
typedef unsigned long long ULL;
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;
}