哈希表|STL使用

news2025/1/23 22:33:36

哈希表

时间复杂度为O(1)

拉链法

把X代表的数字映射到N所在区间,有可能会发生冲突俩个或多个数字映射到1个数

拉链法:把冲突的数字挂起来,用单链表挂起来

一般取模的数要取成质数,而且这个质数离二的n次幂要比较远,这样取冲突的概率是最小的。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstring>
using namespace std;
const int N = 100003;//大于十万的第一个质数是100003
int h[N];//槽
int e[N], ne[N], idx;//单链表
void insert(int x)
{
    int k = (x % N+N)%N;//x%N将数变小,再+N是为了保证数是正数,由于加N之后数会变大,所以最后再模N,k是哈希值
    //把当前x挂到H[k]上
    e[idx] = x;//先把x放入单链表
    ne[idx] = h[k];//先让新节点指向h[K]
    h[k] = idx++;//再让H[K]指向这个节点
}
bool find(int x)
{
    int k = (x % N + N) % N;//先映射x
    //接下来在单链表里面找x
    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 == 'I')
        {
            insert(x);
        }
        else
        {
            if (find(x))//如果能找到x,输出Yes
                puts("Yes");
            else//如果找不到x,输出No
                puts("No");
        }
    }
    return 0;
}

开放寻址法

开放寻址法只开了一个一维数组,该数组一般为题目要求长度的俩到三倍,这样可以降低冲突

跟公交车找空位是同一个道理

一般删除x的时候,若找到了x,则不会真正删掉,而是标记一下x

先找一下大于20w最小的质数

#include<iostream>
#include<cstring>
using namespace std;
const int N = 200003,null=0x3f3f3f3f;//开放寻址法一般开2到3倍,null不在要查找的数据范围内
int h[N];
int find(int x)//若x存在返回x实际所在位置,若x不存在返回x应该存储的位置
{
    int k = (x % N + N) % N;
    while (h[k] != null && h[k] != x)//如果当前位置有数字,并且这个数字不是x
    {
        k++;
        if (k == N)//如果已经走到了结尾,就从头开始看
            k = 0;
    }
    return k;//如果x在数组中,返回的是下标,如果不在数组中,返回的是应该存储的位置
}
int main()
{
    int n;
        scanf("%d", &n);
        memset(h, 0x3f, sizeof h);//先把所有的槽清空
        while (n--)
        {
            char op[2];
            int x;
            scanf("%s%d", op, &x);
            if (*op == 'I')
            {
                int k = find(x);
                h[k] = x;
            }
            else
            {
                int k = find(x);
                if (h[k]==null)//如果能找到x,输出Yes
                    puts("No");
                else//如果找不到x,输出No
                    puts("Yes");
            }
        }
        return 0;
    }

字符串哈希

这样取P和Q可以避免好多冲突

类似于进制转换把字符串转换成数字,把字符串看作P进制的数,最好不要把数字映射成0

如A映射成0,转为10进制A=0,AA=0,AAA=0这样会出错

求出[L,R]这段的哈希值

对于一个字符串:"A B C A B C D E X A C W I N G ABCABCDEXACWINGABCABCDEXACWING"

有前缀哈希数组h hh,则有

h [ 0 ] = 0 h[0]=0h[0]=0

h [ 1 ] = h[1]=h[1]=“A AA” 的哈希值

h [ 2 ] = h[2]=h[2]=“A B ABAB” 的哈希值

h [ 3 ] = h[3]=h[3]=“A B C ABCABC” 的哈希值

h [ 4 ] = h[4]=h[4]=“A B C A ABCAABCA” 的哈希值

⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ······⋅⋅⋅⋅⋅⋅

这里的 h hh 数组存储的是这个字符串的哈希值

比如"A B C D ABCDABCD"这个字符串,看成是 p pp进制的数

A B C D A B C DABCD

( 1234 ) P ( 1 2 3 4)_P(1234)P

= ==( 1 ∗ p 3 + 2 ∗ p 2 + 3 ∗ p 1 + 4 ∗ p 0 ) % Q (1*p^3+2*p^2+3*p^1+4*p^0)\%Q(1∗p3+2∗p2+3∗p1+4∗p0)%Q

这样就把任何一个字符串映射成了[ 0 , Q − 1 ] [0,Q-1][0,Q−1]之间的一个数

P S : PS:PS:

一般不能把一个字母映射成0,比如上面把A映射成0,那么ABCD和BCD的哈希值都是一样的了

经验值:当P = 131 P=131P=131或者P = 13331 P=13331P=13331,Q = 2 64 , 一 般 的 99.99 % 的 情 况 下 不 会 出 现 冲 突 , 冲 突 的 概 率 大 约 是 几 十 亿 分 之 一 Q=2^{64},一般的99.99\%的情况下不会出现冲突,冲突的概率大约是几十亿分之一Q=264,一般的99.99%的情况下不会出现冲突,冲突的概率大约是几十亿分之一

这里我们直接用ULL,因为溢出相当于取模

可以先预处理p数组,之后查询的时候就非常快:

p [ i ] = p [ i − 1 ] ∗ P p[i]=p[i-1]*Pp[i]=p[i−1]∗P

预处理 h hh 哈希数组:

a r r [ i ] = a r r [ i − 1 ] ∗ p + s t r [ i ] arr[i]=arr[i-1]*p+str[i]arr[i]=arr[i−1]∗p+str[i],其 中 s t r [ i ] 只 要 不 为 0 就 行 其中str[i]只要不为 0 就行其中str[i]只要不为0就行

得到一个字符串中的[ l , r ] [l,r][l,r]段子字符串的哈希值是:

a r r [ r ] − a r r [ l − 1 ] ∗ p [ r − l + 1 ] arr[r]-arr[l-1]*p[r-l+1]arr[r]−arr[l−1]∗p[r−l+1]

const int N= 100010,P=131;
typedef unsigned long long ULL;
int n, m;
char str[N];
ULL h[N], p[N];//P用来存储P的多少次方
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;//p的0次方是1
    for (int i = 1; i <= n; i++)
    {
        p[i] = p[i - 1] * P;
        h[i] = h[i - 1] * P + str[i];
    }
    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使用

vecotr长度为10,里面数字全部是3

map可以像数组一样来使用

bitset压位

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/433941.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是深度学习?

目录 简介 深度学习的由来 深度学习未来的趋势 总结 简介 深度学习是在20世纪80年代被提出来的&#xff0c;主要是由加拿大的计算机科学家Geoffrey Hinton、Yoshua Bengio、Yann LeCun等人发起的。Geoffrey Hinton等人在经过多年的研究和实践之后&#xff0c;…

C语言的指针(进阶)

目录 数组指针 数组指针的使用 函数指针 函数指针数组 指向函数指针数组的指针 回调函数 数组指针 数组指针是指针&#xff1f;还是数组&#xff1f; 答案是&#xff1a;指针 数组指针也就是指向一个数组的指针 看下面两条代码&#xff1a; int *p1[10]; int (*p2)[10]; …

Manjaro安装clash-for-windows-bin

安装 安装Clash for Windows yay -S clash-for-windows-bin 配置 命令行进入~/.config/clash/ &#xff0c;配置文件 config.yaml 和 Country.mmdb wget -O config.yaml [订阅链接]wget -O Country.mmdb https://gitee.com/mirrors/Pingtunnel/raw/master/GeoLite2-Country.…

领导给了一千多个需求,这个排序法救了我的命……

什么是MoSCoW排序法&#xff1f; 莫斯科排序法是一种优先级排序法&#xff0c;用于管理需求、任务或功能列表。该方法可以帮助团队确定哪些需求、任务或功能是最重要的&#xff0c;并决定在特定时间段内是否需要完成它们。 所以在对需求进行排序时&#xff0c;可以从以下维度…

优思学院|六西格玛常见问题有哪些?

要实现高质量、高效率和高客户满意度的目标&#xff0c;许多企业采用了六西格玛方法。然而&#xff0c;在实施过程中&#xff0c;往往会遇到各种各样的问题。优思学院会在这里探讨一下几个六西格玛常见问题&#xff0c;并提供解决方案&#xff0c;以帮助企业成功实施六西格玛方…

JSONP数据劫持漏洞

​介绍 JSONP&#xff08;JSON with Padding&#xff09;是 json 的一种"使用模式"&#xff0c;可以让网页从别的域名&#xff08;网站&#xff09;那获取资料&#xff0c;即跨域读取数据&#xff1b;它利用的是script标签的 src 属性不受同源策略影响的特性&#x…

GoNote第二章 Moudles

Go Modules 1. 介绍 Go modules是官方提供的go包管理工具&#xff0c;用于解决go包管理和依赖问题&#xff1b;从1.11开始引入&#xff0c;到现在1.14已经比较完善&#xff0c;1.16已经全面推荐使用&#xff0c;并且默认为开启&#xff1b;Go Modules类似于JS的NPM&#xff0…

校园小助手【GUI/Swing+MySQL】(Java课设)

系统类型 Swing窗口类型Mysql数据库存储数据 使用范围 适合作为Java课设&#xff01;&#xff01;&#xff01; 部署环境 jdk1.8Mysql8.0Idea或eclipsejdbc 运行效果 本系统源码地址&#xff1a; 更多系统资源库地址&#xff1a;骚戴的博客_CSDN_更多系统资源 更多系统…

Apple iWork(Pages、Numbers、Keynote)13.0 - 文档、电子表格、演示文稿

请访问原文链接&#xff1a;https://sysin.org/blog/apple-iwork-13/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 苹果今天将其专为 iOS 和 macOS 设备设计的 iWork 应用套件更新为版本 12 (sysin)&#xff0c;引入了许多新…

高并发服务器之泄峰

文章目录 背景前言解决方案泄峰 泄峰结果总结代码示例 背景 行业&#xff1a; 车联网机器配置&#xff1a;阿里云服务 8核 16G内存 3M带宽 阿里云操作系统单台server接入设备&#xff1a;5w终端产品&#xff1a;GPS定位设备终端与平台通信方式&#xff1a;TCP长链 前言 近期…

Linux中的五种IO模型

Linux中有以下五种IO模型 一、同步阻塞IO&#xff08;Blocking IO, BIO&#xff09; 用户进程发起IO调用后就阻塞线程让出CPU&#xff0c;等待内核处理完毕返回结果再唤醒继续执行。 二、同步非阻塞IO&#xff08;Non-Blocking IO, NIO&#xff09; 用户进程发起IO调用后就…

前端研发提质增效利器,TypeScirpt成功迁移详解

点击蓝字&#x1f446; 关注Agilean&#xff0c;获取一手干货 直播预告&#xff1a;Adapt 系列直播又双叒叕来啦&#xff01;最新一期我们将围绕「版本分支与环境」进行深入探讨&#xff0c;欢迎大家来直播间和主播互动哟&#xff5e; 点击下方右上角红色按钮「预约」&#x1f…

ESP32设备驱动-PAJ7620手势传感器驱动

PAJ7620手势传感器驱动 文章目录 PAJ7620手势传感器驱动2、硬件准备3、软件准备4、驱动实现PAJ7620 将手势识别功能与通用 I2C 接口集成到单个芯片中,形成图像分析传感器系统。 可识别上、下、左、右、前、后、顺时针、逆时针、挥手等9种人手手势。 它还提供内置的接近检测,以…

网络编程及项目思路

计算机和计算机之间通过网络进行数据传输 常见的软件架构&#xff1a; C/S:客户端/服务器 画面可以做的非常精美&#xff0c;用户体验好需要开发客户端&#xff0c;也需要开发服务端用户需要下载和更新的时候太麻烦 B/S:浏览器/服务器 不需要开发客户端&#xff0c;只需要…

java IO流_1

目录 分类 字节流 InputStream OutputStream 文件拷贝 字符流 FileReader FileWriter 处理流 BufferedReader BufferedWriter 文本拷贝 流是从起源到接受的有序数据&#xff0c;通过流的方式允许程序使用相同的方式来访问不同的输入/输出源。 分类 按数据…

SDK(动态链接库dll)的封装技巧

SDK(动态链接库dll)的封装技巧 一、说明 通过上篇文章&#xff0c;我们知道对于封装API&#xff0c;目的为了代码复用等&#xff0c;其中还有一个重要的原因&#xff0c;就是隐藏实现。 说到隐藏实现&#xff0c;在封装C的SDK库&#xff08;动态dll库&#xff09;时&#xff…

【获奖案例巡展】信创先锋之星——浙江省某市区视频能力中心

为表彰使用大数据、人工智能等基础软件为企业、行业或世界做出杰出贡献和巨大创新的标杆项目&#xff0c;星环科技自2021年推出了“新科技 星力量” 星环科技科技实践案例评选活动&#xff0c;旨在为各行业提供更多的优秀产品案例&#xff0c;彰显技术改变世界的力量&#xff0…

【id:33】【20分】C. 分数类(类与构造)

题目描述 完成下列分数类的实现: class CFraction { private: int fz, fm; public: CFraction(int fz_val, int fm_val) ; CFraction add(const CFraction &r); CFraction sub(const CFraction &r); CFraction mul(const CFraction &r);…

elementui的table组件,大量使用v-if导致列表渲染错乱,有的列渲染的值不对,有的列渲染出来的空值解决办法

记录一下&#xff1a; 这是同事碰上的&#xff0c;感觉挺奇怪的就研究了研究。 先说一下&#xff0c;之所以是同事那边碰到的而我这边碰不到这个问题&#xff0c;是因为我这边做 el-table-column 的时候&#xff0c;是先定义的 tableHeader: [...] 然后通过 v-for 遍历出来的…

【Linux】CentOS桥接模式配置静态IP

文章目录 1 前言2 桥接模式和NAT模式有什么区别3 校园网环境下配置桥接模式 1 前言 最近在安装的虚拟机上面用mosquitto搭建MQTT服务器&#xff0c;但是很奇怪的是每次电脑上的测试软件能顺利连接服务器&#xff0c;但是连接电脑热点的外部设备却不行&#xff0c;让我很是困惑。…