zoukankan      html  css  js  c++  java
  • 字符串哈希(进制哈希)

    哈希

      简单来说,哈希相当于一种单向加密,一种映射过程,并且要尽量保证加密后不会重复,通过这种方式来替代一些很费时间的操作

    字符串哈希 也叫进制哈希

          当你想判断两个字符串是否相等时,不知道你有没有过一种想法,将两个字符串通过一些独特方式的计算转换成两个数字,然后判断两个数是否相等不就好了,那么进制哈希就提供了一种转换方式——将这个字符串看成一个base进制的数,因为进制计算的特殊性,可以保证每个数都代表这一种字符串的情况

          当然,你可能会有疑问 当字符串是s1“100000”和s2“50000”,base=5时 算出的结果是('1'-'0')*5^5与('5'-'0')*5^4的答案是相同的(这里方便理解-了‘0’然鹅与找到ASCII表中相差4倍的情况相同)但由于进制的特殊性, 满base进一,所以这种情况被pass了,我们无法控制给出的数据 但我们能改变base值,所以在实际应用中 要让base大于所有能出现的字符的可能,ASCII码最大为127 而大于127的最小质数为131,所以一般base取131即可。

           base的情况解决了,但如果字符串的长度太大,一般的 int 甚至是long long 都有可能存不下,所以我们可以通过对这个数取模来解决,但他还是有个弊端——两个不同的数对mod取余后得到的数是一样的!!这就导致了传说中的哈希冲突……

            我们设置进制(base)为131,模数(mod)为1e9+7,现在我们对一个字符串s进行哈希   

    1        char s[10009];
    2       scanf("%s",s+1);
    3       int len=strlen(s+1);
    4       int base=131,mod=1e9+7; 
    5       for(int i=1;i<=len;i++)
    6       {
    7             hash[i] = ( ( hash[i-1] * base ) + s[i] ) % mod ;
    8       }

         借用这张图片更为直观

           因为哈希的处理是一个字符一个字符的而且计算具有规律性,所以我们还可以取到子串的hash值

    hash[l,r] = ( hash [r] - hash[l-1] * fpow(base,r-l+1) ) %mod
    //fpow(base,r-l+1)为base的(r-l+1)次方

    如何处理哈希冲突??

     1.模数选取大质数

        如果选取合数那么他的剩余系将会有所浪费,如果质数过小将会导致剩余系过小,哈希冲突几率增大

      /* 所谓“剩余系”,就是指对于某一个特定的正整数n,一个整数集中的数模n所得的余数域。*/

     2.双模数哈希

        我们可以通过设置两个不同的哈希方式,对于一个字符串,当且仅当两个哈希值都相同时才判定相当。

            这就相当于是双重加密,应该就很靠谱了吧。

  • 相关阅读:
    signal, sigaction,信号集合操作
    how to create view (windows)
    设计模式-单例模式
    clearcase command (windows 常用的几个)
    struts2提交文件时,出现页面重置又无法返回input现象,我没有解决这个问题
    报错如HTTP Status 404
    srm开发(基于ssh)(3)
    报错HTTP Status 500
    编写程序时候莫名出现<property name="dialect">org.hibernate.dialect.FirebirdDialect</property>
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [bean.xml]: Invocation of init method failed; nested exception is
  • 原文地址:https://www.cnblogs.com/YangKun-/p/12488843.html
Copyright © 2011-2022 走看看