文章目录
hash表 O(1)
840. 模拟散列表
#include <iostream>
using namespace std;
#include<cstring>
const int N = 100003; //取质数
int first_prim(int x) {//输入10^6^ 开始判断条件
for(int i = x; ; i++) { //大于10^6^的第一个质数为1000003 作为mod值
bool flag = true;
for(int j = 2; j * j<= i; j++) {
if(i % j == 0) {
flag = false;
break;
}
}
if(flag) {
cout << i << endl;
break;
}
}
return 0;
}
//一个hash槽h[](存多条链),每个可以拉一条hash链 ,每一条链 e存对应位置元素值 , ne存下一个元素下标 , idx表示当前位置
int h[N],e[N],ne[N],idx;
void insert(int x) //把x映射到 0 ~ N 之间的一个数
{ //如x为10^-9^ 就必须先mod再加N
int k = (x % N + N) % N; //【 (如果余数负数 +N ) % N,余数就变成正数】,映射成正数
e[idx] = x; //存值 (这里就想象单链表插入,把idx指向k位置的下一个位置,k的指针指向idx,当前位置idx++)
ne[idx] = h[k]; //idx->next = k->next = k+1 = h[k] (从0开始插入,k+1下标为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]) //沿着指针链找下一个点的下标 i = i->next (因为都在一条(初始值为-1)的数组上,最后到NULL即为-1)
if(e[i] == x)
return true;
return false;
}
int test_01()
{
int n;
scanf("%d",&n);
memset(h,-1,sizeof(h));
while(n--)
{
char op[2];
int x;
scanf("%s%d",op,&x);
//*op 等效op[0]
if(*op == 'I') insert(x);
else
{
if(find(x)) puts("Yes");
else puts("No"); //puts在<iostream>中
}
}
return 0;
}
开放寻址法:
#include<cstring>
const int N = 200003, null = 0x3f3f3f3f;//每个数没有被使用的数都不在x范围内,作为结束条件
int h[N];
int find(int x)
{
int k = (x % N + N) % N ;
while(h[k] != null && h[k] != x) //如果到最后都没有找到k ,返回k = 0 ,找到就返回k值
{
k ++;
if(k == N) k = 0;
}
return k;
}
//first_prim(200000);大于此数的第一个质数 2000003 取长度N = 2000003
int test_02()
{
int n;
scanf("%d",&n);
memset(h,0x3f,sizeof(h)); //按字节赋值,每个字节0x3f ,所有int四个字节就变成0x3f3f3f3f
while(n--)
{
char op[2];
int x;
scanf("%s%d",op,&x);
int k = find(x); //都有此句,写到外面
if(*op == 'I')//*op 等效op[0]
{
//int k = find(x);
h[k] = x; // 先找的x的映射位置k ,再赋值 x
}
else
{
//int k = find(x);
if(h[k] != null) puts("Yes");
else puts("No"); //puts在<iostream>中
}
}
return 0;
}
***字符串前缀hash法 (高效判断字符串-优于kmp)
typedef unsigned long long ULL; // unsigned long long等效取模 mod 2^64^
const int N = 100010,P = 131; //或1331 统一用 p = 131 记住!
int n,m;
char str[N];
ULL h[N],p[N]; //p数组存储p的多少次方的值 {p^1^,p^2^,p^3^,p^4^,p^5^};
//h[k]存前k个字符的hash值
ULL get(int l,int r) //计算区间hash值
{
return h[r] - h[l - 1] * p[r - l + 1]; //p^l-r+1^
}
int test_03()
{
scanf("%d%d%s",&n,&m,str + 1); //str从1开始存储
p[0] = 1;//P^0^ == 1
for(int i = 1;i <= n;i++) //初始化!!
{
p[i] = p[i - 1] * P; //注意 * 大写P
h[i] = h[i - 1] * P + str[i]; //保证str[i] != 0 就可以
}
while(m--)
{
int l1,l2,r1,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 常用容器
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
vector
string 字符串
pair 【自带了一个比较函数,比较first】
queue
优先队列 (大根堆)
stack
deque 双端队列 (功能全, 但缺点:速度慢很多)
set / multiset
bitset ,压位
#include<bits/stdc++.h> //万能头文件 字节集bits/stdc++.h的头文件
int test_04()
{
vector<int> a;
a.size(); //O(1)
a.empty(); //返回数组是否为空
a.clear(); //并不是所有容器都有
for(int i = 0;i < 10;i++) a.push_back(i);
for(int i = 0;i < a.size();i++) cout << a[i] << " ";
cout << endl;
for(vector<int>::iterator i = a.begin() ;i != a.end();i++) cout << *i << " ";
cout << endl;
//for(auto x : a ) cout << x << " "; //5.11不允许 auto ???
cout << endl;
return 0;
}
int test_05()
{
pair<int , string> p;
p = make_pair(10,"wz");
p = make_pair(20,"abc");
//嵌套 三元组
pair<int, pair<int,string> > pp;
//优先队列(默认大根堆)
priority_queue<int> heap;
int x;cin >> x;
heap.push(-x); //从大到小 【小根堆,输出时输出 (负负得正) -heap.pop() 即可】
cout << heap.top() << endl;
priority_queue<int,vector<int> ,greater<int> > small_heap;
//map的使用
map<string , int> a;
a[];
}
int main() {
test_05();
return 0;
}