码迷,mamicode.com
首页 > 其他好文 > 详细

蓝书《哈希与哈希表》——知识整理

时间:2019-07-20 21:46:22      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:整理   时间复杂度   字符串   mda   小技巧   进一步   优化技巧   元素   dash   

一、前言:

  有些数据不经处理是难以利用的。所谓哈希,就是通过哈希函数将这种难以简单利用的数据(比如矩阵、字符串等等)转化为可以用一个变量表示甚至可以作为数组下标的哈希值。有了哈希值,就可以实现时间复杂度近乎为常数的快速查找与匹配,更简单有效地利用一些复杂数据。

二、字符串哈希:

  即对象为字符串的哈希。常将字符串看做一个不严格的b进制的数(有时数位上的数有可能要比b还要大),转换为10机制后再模一个数p(以便存储)得到哈希值。即定义哈希函数:

    H(C)=(c1*b^(m-1) + c2*b^(m-2) + . . . + c0*b^0)% p

      (c为字符串,m为字符串长度)

  当两字符串的哈希值相同时,我们就认为这两个字符串是一模一样的。显然这样的判断有时会有“冲突”,即相同哈希值的两个字符串可能会不同。而冲突的概率显然与p和b有关。一般来说,p的因数越多,冲突概率越大(故p一般选大素数)。

  做子串匹配时,我们要知道所有子串的哈希值。难道要用O(n^2)的复杂度全部处理出来吗?这里有一个叫做滚动哈希的优化技巧,实质是用了前缀和与递推的思想,同时我们可以用unsigned int 型,用自然溢出时对2^32取模来代替手写取模:

    设H(C,k)为字符串c前 k 个字符构成的字符串的哈希值,发现H(C,k+1)= H(C,k) * b+c[k+1]);

    主串上某一子串c[k]c[k+1]...c[k+len]的哈希值即=H(C,k+len) - H(C,k-1) * b^n; 

  这样只要预处理出b的次幂再用O(n)的时间处理出H(C,1)...H(C,m),主串所有子串的哈希值也就知道了。

  平时常应用与各种字符串匹配问题。为了进一步降低冲突概率,还可以再另处理一组哈希值,称为“双哈希”,此时取模的素数常用1e9+7和1e9+9,这两个孪生素数可以将随机数据的冲突概率降到1/(1000000009*1000000007)(当然还是防不了毒瘤出题人故意出一个卡哈希的数据,OIer与出题人的斗智斗勇永不停息......)

三、哈希表:

  运用哈希可以将大的数据转化为较小的哈希值,同时发现如果哈希函数选取合适,那么相同哈希值的不同元素会非常少。由此提醒我们可以搞一个可以快速查询元素的结构——哈希表:

  在一个相同哈希值的域下记录相应数据。在一个哈希表中查询数据x时,算出x的哈希值h=H(x),将h域下所有的元素与x进行比较(不会很多),得出结果。

  通常用邻接链表实现哈希表,代码这里不写出了,蓝书70页写的很详细。代码中H变量没提到值,应该等于b,注意一下插入数据时先判个重。

  最后有一个小技巧:如果真实数据过大,域下记录的数据可以是模另一个素数的余数,达到“双哈希”的效果。

  

 

蓝书《哈希与哈希表》——知识整理

标签:整理   时间复杂度   字符串   mda   小技巧   进一步   优化技巧   元素   dash   

原文地址:https://www.cnblogs.com/InductiveSorting-QYF/p/11219223.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!