散列表
哈希表
我用的拉链法。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int N = 100003;
vector<int> H[100003];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
char op;
int v;
int x;
//主要难点:负数modN之后还是负数,需要(v%N+N)%N,两次%N是为了照顾正数
while (n -- ){
cin >> op;
if(op=='I'){
cin >> v;
H[(v%N+N)%N].push_back(v);
}
else if(op=='Q'){
cin >> v;
x = (v%N+N)%N;
int flag=0;
for (int i = 0; i < H[x].size(); i ++ ){
if(H[x][i]==v){
flag=1;
break;
}
}
cout << (flag?"Yes":"No") <<endl;
}
}
return 0;
}
字符串哈希
这个比较厉害,其实就是把字符转为了系数,然后字符串的哈希就是一个多项式
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ULL;
ULL h[100100];
ULL p[100100];
int BASE=103;
string s;
int main()
{
int n,m,a,b,c,d;
cin >> n >> m;
cin >> s;
s = " "+s;
p[0]=1;
h[0]=1;
for (int i = 1; i <= n; i ++ ){
p[i] = p[i-1]*BASE;
h[i] = h[i-1]*BASE+s[i];
}
while (m -- ){
cin >> a >> b >> c>> d;
cout << (h[b]-h[a-1]*p[b-a+1]==h[d]-h[c-1]*p[d-c+1]?"Yes":"No")<<endl;
}
}
例子很好理解,最早出现的字符,次数最高,需要通过乘以p来消除。
例子
我们用字母直接表示哈希计算过程,更清晰地展示公式原理。以字符串 "abcabc" 为例,取区间 [2,3] 和 [5,6](子串都是 "bc"),用 B
代表 BASE(基数)。
1. 定义字符与前缀哈希
- 字符串下标从1开始:
s[1]=a
,s[2]=b
,s[3]=c
,s[4]=a
,s[5]=b
,s[6]=c
- 前缀哈希
h[i]
定义:前i个字符的哈希值,计算规则为h[i] = h[i-1]×B + s[i]
2. 计算前缀哈希(字母表示)
h[1] = a (仅第一个字符a)
h[2] = h[1]×B + s[2] = a×B + b (前2个字符"ab"的哈希)
h[3] = h[2]×B + s[3] = (a×B + b)×B + c = a×B² + b×B + c (前3个字符"abc"的哈希)
h[4] = h[3]×B + s[4] = (a×B² + b×B + c)×B + a = a×B³ + b×B² + c×B + a (前4个字符"abca"的哈希)
h[5] = h[4]×B + s[5] = (a×B³ + b×B² + c×B + a)×B + b = a×B⁴ + b×B³ + c×B² + a×B + b (前5个字符"abcab"的哈希)
h[6] = h[5]×B + s[6] = (a×B⁴ + b×B³ + c×B² + a×B + b)×B + c = a×B⁵ + b×B⁴ + c×B³ + a×B² + b×B + c (前6个字符"abcabc"的哈希)
3. 计算 [2,3] 子串的哈希("bc")
公式:子串[l,r]的哈希 = h[r] - h[l-1]×B^(r-l+1)
这里 l=2
,r=3
,r-l+1=2
,所以:
哈希值 = h[3] - h[1]×B²
= (a×B² + b×B + c) - (a)×B²
= a×B² + b×B + c - a×B²
= b×B + c (正好是"bc"的哈希:b×B + c)
4. 计算 [5,6] 子串的哈希("bc")
这里 l=5
,r=6
,r-l+1=2
,所以:
哈希值 = h[6] - h[4]×B²
= (a×B⁵ + b×B⁴ + c×B³ + a×B² + b×B + c) - (a×B³ + b×B² + c×B + a)×B²
= a×B⁵ + b×B⁴ + c×B³ + a×B² + b×B + c - (a×B⁵ + b×B⁴ + c×B³ + a×B²)
= b×B + c (同样是"bc"的哈希:b×B + c)
结论
两个子串 "bc" 的哈希值均为 b×B + c
,因此哈希值相等,判断为相同子串。这直接体现了公式的正确性:相同的子串通过哈希公式计算后,必然得到相同的哈希值。