算法合集之《Hash在信息學竞赛中的一类应用》.docVIP

算法合集之《Hash在信息學竞赛中的一类应用》.doc

  1. 1、本文档共12页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  5. 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  6. 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  7. 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  8. 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
算法合集之《Hash在信息學竞赛中的一类应用》

Hash在信息学竞赛中的一类应用 【正文】 Hash表作为一种高效的数据结构,有着广泛的应用。如果Hash函数设计合理,理想情况下每次查询的时间花费仅仅为O(h/r),即和Hash表容量与剩余容量的比值成正比。只要Hash表容量达到实际使用量的大约1.5倍以上,查询花费的时间基本就可以认为恒为O(1)。 对于一个Hash表,一个好的Hash函数是尤其重要的,因为它能使Hash表保证效率。一个好的Hash函数最显而易见的特征是,能使不相同的东西经过Hash之后只有很小的几率相同。这样能避免过多冲突的产生。 Hash表离不开Hash函数,但是反过来呢?有的时候,Hash函数却是可以离开Hash表的。一个常见的例子就是著名的MD5算法,它是一个Hash函数,但是它的用途往往是对信息进行加密,以验证信息的正确性。换句话说,我们事实上是通过直接比较MD5算出的结果是否相同以推断原文内容是否一致。除了MD5,常用的CRC32校验码和SHA-1算法也是基于类似的想法而产生的。 那么,信息学竞赛中,这样的算法有没有用武之地呢? 本文要讨论的,就是这一类以判重或判等价为目标的Hash函数。让我们来看看例题1。 例题1 多维匹配 题目大意 在一个串中求另一个串第一次出现的位置,很简单,KMP即可。扩展到二维情况,就是求在一个矩阵中求另一个矩阵第一次出现的位置。而如果扩展到k维的情况,又该怎么做呢?待匹配数组X各维的尺寸为N1,N2,…,Nk,模式数组Y各维的尺寸为M1,M2,…,Mk。记N=N1N2…Nk ,M=M1M2…Mk 。保证k≤10,Ni≥Mi,而N和M都不超过500000。 算法分析 本题常见的算法是多维情况的KMP,先算1维时的匹配情况,然后处理2维,3维……直到N维时的情况。时间复杂度为O(k*(N+M))。但是它难以理解和记忆,也不容易在比赛中的短短几个小时完成和写对。 朴素的解法相对易于实现,但是使朴素算法很容易想到,而且针对数据又很容易制作,因此只有在完全没有思路的时候才值得一试。 有没有第三种选择呢?答案是肯定的。朴素的解法相当于枚举了每个起点(起点数量显然不会超过N)并加以判断,然而判断两个子数组是否相同的时间复杂度高达O(M),这就是导致朴素算法在遇到针对数据的情况下很慢的原因。能不能在比较两个子数组之前先快速地排除一些明显不可能的情况呢?由于很容易构造出仅有一个字符不同的数据,不管采用什么顺序比较都会消耗大量的时间。 Hash函数在这里派上了用场。我们可以对每个尺寸与模式数组一样的子数组计算一个Hash值。显然,只有当某个子数组的Hash值与模式数组的Hash值一样,它们才值得比较。 多维的KMP要从1维的情况开始考虑,并推广至高维。那么这种计算Hash函数的匹配算法我们也可以先考虑一维的情况——就是Rabin-Karp算法。 对于一个字符串S,可以使用这个函数求出其Hash值: 那么,模式串Y的Hash值就可以轻松地求出。记待匹配串X从第i个字符开始的长度为M的子串为Si,则不难发现f(Si+1)和f(Si)的关系: 换个角度,如果不考虑mod q,这个函数就是把字符串看作一个p进制数求出的值,这样,Xi+1就是Xi “左移”一位,然后去掉最前面一位,再加上右面新进来的一位得到的。因此上面的递推公式也是显然的。 有了这个递推公式,不难在线性时间内求出X的所有长度为M的子串的Hash值。 现在把问题扩展到高维的情况。不难发现要计算的Hash值的个数仍然不超过N个,可见,只要有合适的递推方法,仍然可以在线性时间内求出所有子矩阵的Hash值。事实上,一个M1行,M2列的子矩阵可以被看作是M2个“竖条”组成的一个串。我们可以先把每个长度为M1的“竖条”计算出一个Hash值,然后再计算二维情况的Hash值。 需要注意的一点是,在计算一维的Hash值(“竖条”的Hash值)和计算二维的Hash值时使用的b值不能一样,不然不难想到下面反例: 它们并不相同,但是Hash的结果肯定一样。这就违背了使用Hash的初衷。因此,在第一维的计算和第二维的计算中要使用不同的p值。 二维情况时,求出所有长度为M1的“竖条”所需要花费的时间是O(N)的,然后把这些竖条的Hash值看作“字母”计算横向的Hash值(即各个子矩阵的Hash值),所花费的时间也是O(N)的。总时间复杂度仍然是O(N)的。 二维情况的Hash函数为(len1(S)和len2(S)分别表示S在两个维度上的大小): 类似地,记待匹配矩阵X从第i1行,第i2列为左上角的M1行,M2列的子矩阵为,我们有递推式: 式中和都是一维情况下的Hash值,即预先计算出的“竖条”的Hash值。 扩展到k维情况,则不难想到,先算出所有尺寸为M1×M2×…×Mk-1的子数

您可能关注的文档

文档评论(0)

df9v4fzI + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档