zoukankan      html  css  js  c++  java
  • 哈希算法

    2019.7.2

    哈希算法(Hash)

    通过一个哈希函数H,将一种数据转化为能够用变量表示或是直接就可作为数组下标的数,通过哈希函数转化得到的数值我们称之为哈希值。

    字符串Hash

    寻找长度为n的主串S中的匹配串T(长度为m)出现的位置或次数的问题属于字符串匹配问题.
    1. 朴素算法(O(m))
    枚举所有起始位置,直接检查是否匹配
    2. 字符串Hash
    比较长度为m的主串S的子串的哈希值与T的哈希值是否相等
    (注:其实后面学的KMP可以解决大部分字符串Hash问题,但“从主串中选出两子串判断是否匹配”的问题例外)

    一、求哈希值------滚动哈希

    选取两互质常数b,h(b<h),假设字符串(C=c_1c_2······c_m)
    定义哈希函数(H(C)=(c_1b^{m-1}+c_2b^{m-2}+···+c_mb^0)modh)
    (相当于把字符串看作b进制数)
    设H(C,k)为前k个字符构成字符串的哈希值
    则:(H(C,k+1)=H(C,k)*b+C_{k-1})

    例如C="ACDA"(A->1,B->2)
    (H(C,1)=1)
    (H(C,2)=1*b+3)
    (H(C,3)=1*b^2+3*b+4)
    (H(C,4)=1*b^3+3*b^2+4*b+1)
    因此任意字符(C'=c_{k+1}c_{k+2}···c_{k+n})的哈希值为
    (C=c_1c_2···c_m)

    [H(C')=H(C,k+n)-H(C,k)*b^n ]

    那么只要预求得(b^n),就可用(O(1))得任意字符串的子串哈希值
    整个算法时间复杂度为(O(n+m))
    [!在实现算法时,利用32或64位无符号整数计算哈希值,取(h=2^{32})(2^{64})实现自然溢出取模。]

    二、字符串Hash的正确性

    常常认为竞赛题目不会出现不同的字符串哈希值相等的情况。实际上根据生日悖论,对于哈希值在([0,n))内均匀分布的哈希函数出现不同字符哈希值相等的期望步数是(O(sqrt(n))).
    什么是生日悖论?

    措施:

    用“双哈希”降低概率,取不同模数,把不同模数算出的哈希值记下来,只有几个哈希值都满足条件才判定字符串匹配。
    (分别取(h=10^9+7)(h=10^9+9),就几乎不可能发生冲突,因为它们是一对“孪生质数”。)
    什么是孪生质数?

  • 相关阅读:
    webpack 3.X学习之Babel配置
    git常用命令记录
    let const
    数据存储之HTTP Cookie
    cookie sessionStorage localStorage 之间的关系
    数据存储之Web存储(sessionStorage localStorage globalStorage )
    express官网学习笔记
    最近计划
    node.js进阶话题
    node.js核心模块
  • 原文地址:https://www.cnblogs.com/HHHG/p/11119628.html
Copyright © 2011-2022 走看看