本节内容:哈希表与STL简介。
一、哈希表
存储结构(解决映射冲突的方法:开放寻址法、拉链法)、字符串哈希的方式。
哈希表可以通过函数的映射关系f(x)快速找到一个数x是否在一个集合当中存在过,好的哈希函数时间复杂度可以近似为O(1),而暴力的做法则是需要遍历一遍数组,时间复杂度最慢为O(n)。这是一个典型的用空间换时间的方法,一个好的哈希函数也是关键,可以使得冲突最小。
(1)、拉链法
在冲突的位置加上一个单链表。
acwing840
#include<iostream>
#include<cstring>
using namespace std;
const int N = 100003;
int h[N],e[N],ne[N],idx = 0;
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;
scanf("%d",&n);
memset(h,-1,sizeof(h));
while(n--){
char op[2];
int x;
scanf("%s%d",op,&x);
if(op[0] == 'I'){
Insert(x);
}
else{
if(find(x)) printf("Yes\n");
else printf("No\n");
}
}
return 0;
}
(2)、开放寻址法
将数组的大小设置成集合大小的两到三倍最好,再取大于等于这个数的最小质数
#include<iostream>
#include<cstring>
using namespace std;
//ACM中常用的无穷大常量——0x3f3f3f3f,0x3f3f3f3f的十进制是1061109567,是10^9级别的,而一般场合下
//的数据都是小于10^9的,所以它可以作为无穷大使用而不致出现数据大于无穷大的情形。
const int N = 200003,null = 0x3f3f3f3f;
int h[N],idx = 0;
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 main(){
int n;
scanf("%d",&n);
memset(h, 0x3f, sizeof h);
while(n--){
char op[2];
int x;
scanf("%s%d",op,&x);
int k = find(x);
if(op[0] == 'I'){
h[k] = x;
}
else{
if(h[k] != null) printf("Yes\n");
else printf("No\n");
}
}
return 0;
}
二、字符串哈希
字符串哈希可能会有冲突,在p,q取特定值时,基本不会出现冲突。
可以利用数字来表示一个特定的字符串,再利用前缀和来计算每一个子串的哈希值,利用哈希值是否相等来判断子串是否相等。注意比较的时候还要将小的值呈上p的(r-l+1)次方,使其左移。具体公式如下:
用unsigned long long来存储所有的h,如果数据溢出相当于取模。
#include<iostream>
#include<cstring>
using namespace std;
typedef unsigned long long ULL;
const int N = 100010,P = 131;
int n,m;
ULL h[N],p[N];
char str[N];
ULL 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;
}
三、STL简介
1、vector:
变长数组,倍增的思想
2、string:
字符串,substr,c_str()
3、queue,priority_queue:
push(),pop(),front()
4、stack:
push(),top(),pop()
5、deque:
双端队列
6、set,map,multiset,multimap:
7、unordered_set,unordered_map,unordered_multiset,
unordered_multimap:
hash表实现
8、bitset:
压位