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

    哈希

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

    字符串哈希 也叫进制哈希

    当你想判断两个字符串是否相等时,不知道你有没有过一种想法,将两个字符串通过一些独特方式的计算转换成两个数字,然后判断两个数是否相等不就好了,那么进制哈希就提供了一种转换方式——将这个字符串看成一个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进行哈希

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

    借用这张图片更为直观


    因为哈希的处理是一个字符一个字符的而且计算具有规律性,所以我们还可以取到子串的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.双模数哈希

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

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

  • 相关阅读:
    Unity 执行命令行
    c#中的特性,以及一些思考
    miniui禁用combobox
    给textarea赋值并可编辑
    js不允许input输入空格
    使用OPENROWSET函数连接并访问远程数据库数据
    miniui 换页符点击无效
    AJAX基本结构及使用
    SQL Server查询数据库中包含某个值的表和字段
    js实现input输入框只能输入数字的功能
  • 原文地址:https://www.cnblogs.com/YangKun-/p/12944530.html
Copyright © 2011-2022 走看看