2.2数据结构哈希表
#include <iostream>
#include <cstring>
using namespace std;
const int N = 100003;
int h[N] , e[N] , ne[N] , idx;//h是数组头,e是存的插的链表的值,ne是其下一个的idx
void insert(int x)
{
int k = (x % N + N) % N;//负数mod之后还是负数,这是为了防止负数出现
e[idx] = x , ne[idx] = h[k] , h[k] = idx++;
}
bool query(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;
scanf("%d" , &n);
memset(h , -1 , sizeof h);//把h全部初始化成空
while (n -- ){
char str[2];
int x;
scanf("%s%d" , str , &x);
if(str[0]=='I') insert(x);
else{
if(query(x)) printf("Yes\n");
else printf("No\n");
}
}
return 0;
}
哈希表的拉链法
2.开放寻址法(y总用得较多,因为只用开一个数组)
一共N个数,经验上开2N~3N的数组,先找到大于2N的第一个质数,然后开这么大的数组,定义一个超过数据范围的null,然后把数组全部初始化成0x3f3f3f3f,因为一个int有32位,memset是4位4位来初始化,写成0x3f就变成了0x3f3f3f3f。精华在于find函数,如果h函数包含x,返回的是x所在位置;如果没有,返回的是第一个找到的空坑。
代码如下:
#include <iostream>
#include <cstring>
using namespace std;
const int N = 100003;
int h[N] , e[N] , ne[N] , idx;//h是数组头,e是存的插的链表的值,ne是其下一个的idx
void insert(int x)
{
int k = (x % N + N) % N;//负数mod之后还是负数,这是为了防止负数出现
e[idx] = x , ne[idx] = h[k] , h[k] = idx++;
}
bool query(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;
scanf("%d" , &n);
memset(h , -1 , sizeof h);//把h全部初始化成空
while (n -- ){
char str[2];
int x;
scanf("%s%d" , str , &x);
if(str[0]=='I') insert(x);
else{
if(query(x)) printf("Yes\n");
else printf("No\n");
}
}
return 0;
}
字符串哈希:
把字符串的每个字母看成一个值,以P进制来表示的值,P按经验取131或者13331,字符串ABCD就等于A*P^3+B*P^2+C*P+D,然后对此余一个数Q,一般Q取2^64,我们可以用unsigned long long来存数,相当于取余了。
KMP算法能做的哈希也可以,除了循环节之外。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ULL;
const int N = 100010 , P = 131;
ULL h[N] , p[N];
int n , m;
char str[N];
int get(int l , int r){
return h[r] - h[l-1]*p[r-l+1];
}
int main(){
scanf("%d%d%s",&n,&m,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;
scanf("%d%d%d%d" , &l1 , &r1 , &l2 , &r2);
if(get(l1,r1)==get(l2,r2)) puts("Yes");
else puts("No");
}
return 0;
}
e