一个思想:哈希进制+单向加密(使值不能高概率重复)
三个操作:初始化哈希值,insert集合,查找集合中
处理问题:%mod->哈希冲突->用表头表示相等的%mod值,链表内存放真值
例一:活动 - AcWing
模板题:
用拉链法/就是类似于邻接表。存值
#include<iostream>
#include<cstring>
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(){
int n;
cin >> n;
memset(h, -1, sizeof h);
while(n--)
{
char op[2];
int x;
scanf("%s%d",op,&x);
if(*op=='I') insert(x);
else
{
if(find(x)) puts("Yes");
else puts("No");
}
}
return 0;
}
这种是开放寻址法
#include<iostream>
#include<cstring>
//开放寻址法
using namespace std;
const int N = 200003, null = 0x3f3f3f3f;
int h[N];
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 main(){
int n;
cin >> n;
memset(h, 0x3f3f3f3f, sizeof h);
while(n--)
{
char op[2];
int x;
scanf("%s%d",op,&x);
if(*op=='I')
{
h[find(x)] = x;
}
else
{
if(h[find(x)]!=null) puts("Yes");
else puts("No");
}
}
return 0;
}
例二:字符串哈希
这个是给了一个字符串,让求不同的子串是否相同。得到子串hash--get()
#include <iostream>
using namespace std;
typedef unsigned long long ULL;
const int N = 1e5 + 10, P = 131;
int h[N], p[N];
int n, m;
char str[N];
ULL get(int l,int r)
{
return h[r] - h[l - 1] * p[r - l + 1];
}
int main(){
cin >> n >> m;
scanf("%s",str+1);
//预处理
p[0] = 1;
for (int i = 1; i <= n; i++)
{
h[i] = h[i - 1] * P + str[i];
p[i] = p[i - 1] * P;
}
while(m --)
{
int l1, r1, l2, r2;
cin >> l1 >> r1 >> l2 >> r2;
if(get(l1,r1)==get(l2,r2))
puts("Yes");
else
{
puts("No");
}
}
return 0;
}
2P3370 【模板】字符串哈希 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这个是给了多个字符串,问有多少种不同的。
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
typedef unsigned long long ULL;
const ULL N = 10010, P = 131, mod = 1000;
int n, ans;
ULL h[N], e[N], ne[N], idx;
void insert(ULL x)
{
int tmp = x % mod;
e[idx] = x;
ne[idx] = h[tmp];
h[tmp] = idx ++;
}
bool find(ULL x)
{
int tmp = x % mod;
for(int i = h[tmp]; i != -1; i = ne[i])
{
if(e[i] == x) return true;
}
return false;
}
int main()
{
cin >> n;
memset(h, -1, sizeof h);
while(n -- )
{
char s[2000];
cin >> s;
//字符串哈希化
ULL hs = 0;
for(int i = 1; i <= strlen(s); i ++ )
{
hs = (ULL)hs * P + (ULL)s[i];
}
if(!find(hs))
{
insert(hs);
ans ++;
}
}
cout << ans << endl;
return 0;
}
用vector容器:
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int mod = 1000, P = 131;
int ans;
int n;
vector<string> v[mod];
void solve(string s)
{
int hs = 0;
for(int i = 0; i < s.size(); i ++ )
{
hs = (hs * P + s[i]) % mod;
}
for(int i = 0; i < v[hs].size(); i ++ )
{
if(v[hs][i] == s) return;
}
v[hs].push_back(s);
ans ++;
}
int main()
{
cin >> n;
while(n -- )
{
char s[2000];
cin >> s;
solve(s);
}
cout << ans << endl;
return 0;
}