在滚动散列中,散列函数的除法方法中使用的素数与为数字选择的基数之间的关系是啥?

Posted

技术标签:

【中文标题】在滚动散列中,散列函数的除法方法中使用的素数与为数字选择的基数之间的关系是啥?【英文标题】:In a rolling hash what is the relationship between the prime used in the division method of the hash function and the base chosen for the numbers?在滚动散列中,散列函数的除法方法中使用的素数与为数字选择的基数之间的关系是什么? 【发布时间】:2016-04-02 21:38:41 【问题描述】:

我正在自学麻省理工学院的算法导论。有一个详细介绍抽象数据类型 Rolling Hash 的背诵视频。这是该视频的注释链接(第一页是关于滚动哈希的):Recitation 9 Notes

视频中使用的示例是尝试在大小为 n 的较大字符串中搜索大小为 k 的字符串(例如在文档中搜索单词)。滚动哈希可以使此任务在 O(n) 中运行。

这个想法是你有一个大小为 k 的窗口,它从较大字符串的开头开始。在每个步骤中,您都会在窗口中散列字符串并将其与您正在搜索的字符串的散列值进行比较。如果哈希值不匹配,则您没有找到要搜索的字符串,因此您将窗口向前滚动一个字符并重试。

为了说明其工作原理,有必要将单个字符串字符视为基数 b 的整数(此基数可以是任何值,但可能是可能的字符数,例如 ASCII 的 256)。字符串变成整数列表。当您向前“滚动”搜索窗口时,您使用称为“追加”和“跳过”(或“弹出”)的滚动哈希操作:您消除(跳过或弹出)列表中的第一个整数,并附加下一个整数是在文件列表中。该视频深入介绍了如何在 O(1) 中从一个窗口的散列到下一个窗口的散列,但使用的散列函数只是简单的模函数(在上面的链接注释中很容易看到)。

有一个观众的问题,以我无法理解的方式回答:

AUDIENCE:p(模函数中使用的素数) 总是必须小于基数,或者可以是什么?

教授:它可以比底座大。所以如果我不想拥有 很多误报,然后假设我的基数是 256,因为那是 额外的字符。我之前在争论假的数量 我所拥有的积极因素基本上是 1/P。所以我希望 p 尽可能接近 字长尽可能。所以 p 将在 2 到 40 亿之间。所以 肯定更大。它可以以任何一种方式工作。如果大一点就更好了 对于我们在那里使用的算法。

首先,如果在简单散列函数的模函数中使用素数 p,那么发生冲突的概率(假设简单均匀散列)是 1/P,对吗?说 P 应该尽可能接近字长是什么意思?

我希望这对将来尝试通过自学学习这门课程的人有所帮助。

【问题讨论】:

【参考方案1】:

两者之间没有任何关系。基数是根据输入的大小来选择的,而素数的选择要使其大到足以产生误报的可能性很小,但又小到可以方便/快速地进行计算。

您确实需要确保它们互质(因为p 是质数,这意味着它不应该是基数的一个因素)。如果p 大于基数,则可以保证这一点,因此应该不是问题。

P 应该尽可能接近字长是什么意思?

字长是可以快速执行计算的架构的“自然”大小。例如,在 32 位机器上,字长为 32 位,因此您通常希望将哈希存储在 32 位无符号整数中,并使用接近 232 的素数值,以便散列值覆盖大部分可能的 32 位值。

【讨论】:

以上是关于在滚动散列中,散列函数的除法方法中使用的素数与为数字选择的基数之间的关系是啥?的主要内容,如果未能解决你的问题,请参考以下文章

使用来自另一个散列的值作为散列名称检查散列中是不是存在键

简单(编码)安全散列函数

如何交换散列中的键和值

用于从Nosql数据的散列中获取数据的通用ruby方法实现

如何避免嵌套散列中缺少元素的 NoMethodError,而无需重复的 nil 检查?

在 rabin-karp 滚动哈希中选择基数和模素数