哈希表与离散化

一、字符串哈希

1. 什么是哈希

        哈希算法是:通过哈希函数将字符串、较大的数等转换为能够用变量表示的或者是直接作为数组下标的数,通过哈希算法转换到的值,称之为哈希值。哈希值可以实现快速查找和匹配。

        比如:用数组下标计数法,统计一个字符串,每种字母出现的次数就是一个简单的哈希,将每个字母都映射为了对应的 A s c i i 码。


2. 如何构造哈希

        原理:将字符串中的每一个字母都看作是一个数字(例如:从 a - z,视为 1 - 26 );将字符串视为一个是 b 进制的数。(注意:不能映射为 0,因为如果a 为 0,那么 a、aa、aaa 的值将都为 0)

        比如:可以将字符串 s = " abcd "视为 26 进制的整数,则可以计算出:hash(s)= 1 * 26 的立方 + 2 * 26 的平方 + 3 * 26 的一次方 + 26 的 0 次方,如果字符串很长,h ( s )很容易超出 long long 范围内。

        选取两个合适的互质常数 b 和 h ( b < h ),其中h要尽可能的大一点,为了降低冲突(不同字符串计算到同一个哈希值)的概率。

        一般来说:b 取 131 或 13331,h 取 2^{64},最终产生的哈希值的冲突的概率极低。

        假设字符串 C=c1c2c3...cm,定义哈希函数:

        H(c)=(c_{1} * b^{m-1} + c_{2}*b^{m-2} + ... +c_{m} * b^{0}) mod(h)


3. 滚动哈希优化

        如果针对一个很长的字符串,判断其中两个长度为 len 的子串是否相同,如果采用O( len )的时间复杂度计算出对应的子串 hash,那和直接取出子串比较的时间复杂度并无差异,因此我们需要使用滚动哈希优化的技巧,可以在O( 1 )的时间复杂度下取出子串的 hash 值。

       (1)滚动计算到前缀哈希 h ( k )

          设:h ( k )为字符串的子串的哈希值,(先不考虑取 MOD ):

           h(k+1)=h(k)*b+c_{k+1}; 

          类比 10 进制理解该公式,比如 10 进制的 12345,取出前 3 个数123,如果要去前 4 个数,可以使用:123 * 10(进制)+ 4(c_{k+1})= 1234 的方法来取出。


      (2)利用前缀哈希 H ( k ) 计算区间哈希值。

          设:

          H(R)=c_{1}*b^{R-1}+...+c_{L-1}*b^{R-L+1}+c_{r}*b^{0}

          H(L-1)=c_{1}*b^{L-2}+...+c_{L-1}*b^{0}

          H(L,R)=H(R)-H(L-1)*b^{r-l+1}

          因此,求 L ~ R 之间的哈希值:h[R]-h[L-1]*b^{r-l+1}

          由上述公式可知,只需要预处理出 b^{m},就可以在O(1)的时间内求得任意子串的哈希值。


       (3)时间复杂度

           综上,如果在一个长度为 n 的字符串中,任意取长度为 m 的子串进行匹配,时间复杂度为O(n+m)。


二、哈希表

1. 哈希表原理

(1)使用数组下标直接标记元素

        哈希表(也叫散列表):是一种高效的、通过把关键码值映射到表中的一个位置来访问记录的数据结构。

        类似字符串,查找的时间复杂度是常数时间,缺点是:需要消耗更多的内存。

        现在要存储和使用下面的线性表:A(12,83,284,49,183,13491,58)

        为了用O(1) 的时间实现查找,可以开一个一维数组 A[ 1 ... 13491 ],使得 A[ key ] = key,但显然造成了空间上的很大浪费,尤其是数据范围很大时。


(2)除余法构造哈希值

        为了使空间开销减少,我们可以使用第二种方法加以优化,设计一个哈希函数 H(key)=key mod 17,然后令 A[ H ( key ) ] = key,这样一来定义一个一维数组 A[0 ... 16]就以足够,这种方法就是哈希表。

        但是这样会造成哈希冲突,比如H(2)和H(19)的值都是 2.

        这里与字符串 Hash 有所不同,可能不论我们怎样选用哈希函数,还是很难避免产生冲突。

        因此我们考虑对每一个哈希值记一个链表(其实也就相当于邻接表),把所有等于同一个哈希值的数字都存储下来,而查询只要遍历对应的链表即可,这样实际复杂度取决于查询的链表长度,也可以看做是常数级。

        例如:我们定义哈希函数H( x ) = x mod 16,对数组A(12,83,284,49,183,13491,58)进行哈希运算后,插入一些数据的效果如下图:

        


(3)哈希函数的构造

        取余法构造哈希:H(key)= key % b,为了避免冲突,一般为能够存储下来并且尽量大的素数(一般情况下我们根据空间取 10 ~ 6 左右的素数)。一般地说如果 b 的约数越多,那么冲突的几率也就越大。

2. 使用数组模拟邻接表

(1)插入关键操作:

v = hash(x);//计算 x 的哈希值
idx++;
e[idx]=x;
ne[idx]=h[v];
h[v]=idx;

(2)查找关键操作:

int v = hash(x);//计算 x 的哈希值
//循环链表
for(int i=h[v];i!=0;i=ne[i]){if(e[i]==x){return 1;}
}

例如:读入整数 2 5 6 8 3 11,假设 h[ x ] = x % 6。

则:每个元素的哈希值是 2 5 0 2 3 5。

存储数组如下:

element 数组:按读入的顺序,存储每个元素的值。

  next 数组:next [ i ]存储和element [ i ]哈希值相同的上一个数的编号。


三、离散化

1. 什么是离散化

        离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小,例如:

        原数据:1,999,100000,15:处理后:1,3,4,2;

        原数据:{100,200},{20,50000},{1,400};

        处理后:{3,4},{2,6},{1,5};

        离散化本质上可以看成是一种特殊的哈希,其保证数据在哈希以后仍然保持原来的全偏序关系,用于解决:影响最终结果的只有元素之间的相对大小关系,这一类的问题。

2. 离散化的步骤

        离散化存在的步骤:

        (1)数组中有重复的元素,因此需要去重复;

        (2)计算出数组中每个值a [ i ]离散化后的值是多少:二分:

离散化数组:

离散化 vector:


最后

制作不易,点个赞吧!!!

制作不易,点个赞吧!!!

制作不易,点个赞吧!!!

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

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

相关文章

一步到位:如何在卡内基梅隆大学计算机科学学院官网下载并安装ACME软件

想要在卡内基梅隆大学计算机科学学院官网下载ACME软件&#xff1f;下面是详细的操作步骤&#xff01; 1. 访问官网 首先&#xff0c;打开卡内基梅隆大学计算机科学学院的官方网站。 2. 搜索ACME软件 在官网首页的搜索框中输入“acme”&#xff0c;然后按下回车键。 3. 找到下载…

GPIO之EMIO按键控制LED——ZYNQ学习笔记3

一、EMIO简介 ZYNQ GPIO 接口信号被分成四组&#xff0c;分别是从 BANK0 到 BANK3。其中 BANK0 和 BANK1 中共计 54个信号通过 MIO 连接到 ZYNQ 器件的引脚上&#xff0c;这些引脚属于 PS 端&#xff1b; 而 BANK2 和 BANK3 中共计 64 个信号则通过 EMIO 连接到了 ZYNQ 器件的 …

云栖实录 | 阿里云 OpenLake 解决方案重磅发布:多模态数据统一纳管、引擎平权联合计算、数据共享统一读写

新一轮人工智能浪潮正在重塑世界&#xff0c;以生成式 AI 为代表的技术快速应用&#xff0c;推动了数据与智能的深化融合&#xff0c;同时也给数据基础设施带来了全新的变革与挑战。面向 AI 时代的数据基础设施如何构建&#xff1f;底层数据平台架构在 AI 时代如何演进&#xf…

[linux 驱动]regmap子系统详解与实战

目录 1 描述 2 结构体 2.1 regmap 2.2 regmap_bus 2.3 regmap_config 3 regmap 操作函数 3.1 regmap 申请与初始化 3.1.1 regmap_init_i2c 3.1.2 regmap_init_spi 3.1.3 regmap_exit 3.2 regmap 设备访问 API 函数 3.2.1 regmap_read 3.2.2 regmap_write 4 示例 1…

react组件入门

react应用程序就是由一个个组件搭建而成。组件有类组件和函数组件两种。 我们之前使用create-react-app创建了app&#xff0c;src下放的就是我们应用的源代码&#xff0c;我们基于这些已生成的文件&#xff0c;来学习和验证组件。 类组件 这里我们创建PostList.js更改这个ap…

Java基础——字节流和字符流

字节流和字符流的用法几乎完全一样&#xff0c;区别在于字节流和字符流所操作的数据单元不同&#xff0c;字节流操作的单元是数据单元是8位的字节&#xff0c;字符流操作的是数据单元为16位的字符。 为什么要有字符流&#xff1f; Java中字符是采用Unicode标准&#xff0c;Un…

论文笔记(四十六)RobotGPT: Robot Manipulation Learning From ChatGPT

xx RobotGPT: Robot Manipulation Learning From ChatGPT 文章概括摘要I. 介绍II. 相关工作III. 方法论A. ChatGPT 提示机器人操作B. 机器人学习 IV. 实验A. 衡量标准B. 实验设置C. 模拟实验D. 真实机器人实验E. AB测试 V. 结论 文章概括 引用&#xff1a; article{jin2024r…

关于养育孩子的一点想法

我们许多人总是很看重结果&#xff0c;不重视过程&#xff0c;在工作中有时候确实会这样&#xff0c;但这种想法会经常蔓延到生活中&#xff0c;比如养育孩子&#xff0c;我们总有一个目标&#xff0c;希望他成才&#xff0c;实现某种理想&#xff0c;弥补你人生中的某种缺憾&a…

第18届全国热管会议举办,积鼎科技分享「环路热管相变传热仿真」前沿实践

第18届全国热管会议于9月20日至22日在海滨城市日照举行&#xff0c;该会议由中国工程热物理学会热管专业组主办&#xff0c;山东大学和日照市科学技术协会联合承办&#xff0c;汇聚了全国热管技术领域的专家学者及企业代表。在该会议上&#xff0c;积鼎科技在热管仿真方面的成果…

使用Nginx反向代理为OneAPI配置https访问

OneAPI在实现大模型访问的过程中提供了接近商业化的API生成服务&#xff0c;在商业化运用过程中&#xff0c;使用https加密访问可以提高访问的安全性。那么如何为OneAPI设置https访问呢&#xff1f;接下来&#xff0c;我们就使用Nginx的反向代理实现这一目标。 Nginx是一款高性…

C++ | Leetcode C++题解之第435题无重叠区间

题目&#xff1a; 题解&#xff1a; class Solution { public:int eraseOverlapIntervals(vector<vector<int>>& intervals) {if (intervals.empty()) {return 0;}sort(intervals.begin(), intervals.end(), [](const auto& u, const auto& v) {retur…

应用层 II(文件传输协议FTP)【★★】

&#xff08;★★&#xff09;代表非常重要的知识点&#xff0c;&#xff08;★&#xff09;代表重要的知识点。 一、文件传输协议&#xff08;FTP&#xff09; 文件传送协议 FTP&#xff08;File Transfer Protocol&#xff09;是互联网上使用得最广泛的文件传送协议。FTP 提…

如何使用ssm实现基于VUE.js的在线教育系统+vue

TOC ssm683基于VUE.js的在线教育系统vue 研究背景和来源 目前的网站平台类系统已各种各样&#xff0c;涉及到生活中的每一个部分。购物类、管理类、信息统计类、办公类、官网类等非常丰富。我国各类网站的发展已非常成熟&#xff0c;这些系统依靠网络和计算机技术不断完善发…

Servlet入门:服务端小程序的初试(自己学习整理的资料)

目录 一.前言 二.建立基础结构​编辑 三.具体步骤 找到Tomcat文件并打开Tomcat。 在webapps中创建一个自己的文件夹。 在classes中新建一个Java文件。 在lib中导入需要的jar文件包。 配置环境变量 在Java文件的目录下打开cmd并输入 javac -d . HelloServlet.java进行…

鸿蒙OpenHarmony【小型系统内核(用户态启动)】子系统开发

用户态启动 用户态根进程启动 根进程是系统第一个用户态进程&#xff0c;进程ID为1&#xff0c;它是所有用户态进程的祖先。 图1 进程树示意图 根进程的启动过程 使用链接脚本将如下init启动代码放置到系统镜像指定位置。 #define LITE_USER_SEC_ENTRY __attribute__((s…

关于Hadoop的详细步骤及方案案例

Hadoop 是一个开源的分布式计算平台&#xff0c;主要用于处理大规模数据集。以下是 Hadoop 的详细步骤及一个方案案例。 一、Hadoop 安装步骤 安装 Java Hadoop 需要 Java 运行环境&#xff0c;确保安装了 Java JDK&#xff0c;并设置好环境变量。 下载 Hadoop 从 Hadoop 官方网…

4.1章节python中顺序结构

顺序结构&#xff08;Sequential Structure&#xff09;是最基本、最简单的程序结构。 顺序结构意味着程序中的语句将按照它们在代码中出现的顺序依次执行。这是大多数编程语言中最直观和自然的执行方式。 在Python中编写顺序结构的程序时&#xff0c;你只需将语句按照你希望它…

TypeScript入门 (四)面向对象

引言 大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年9月学习赛的TypeScript学习总结文档。本文旨在全面介绍 TypeScript 中的面向对象编程&#xff08;OOP&#xff09;思想及其高级特性&#xff0c;…

8.13霍夫变换-直线检测

基本概念 霍夫变换&#xff08;Hough Transform&#xff09;是一种用于检测图像中特定形状&#xff08;如直线、圆、椭圆等&#xff09;的技术。在OpenCV中&#xff0c;霍夫变换主要用于检测直线和圆形。这里我们将详细介绍如何使用OpenCV中的霍夫变换来检测直线。 霍夫变换&…

Cloudflare为网站添加AI审计 可检查AI爬虫何时抓取和抓取频次以及直接屏蔽爬虫

网络服务提供商 Cloudflare 宣布即日起为所有网站 (包括免费托管的网站) 带来 AI 审计功能&#xff0c;该功能目前处于测试阶段&#xff0c;可以分析 AI 公司的爬虫和抓爬数据。新的 AI 审计工具 (Cloudflare AI Audit) 主要提供 AI 公司的爬虫何时到网站来抓取数据、抓取的数据…