字符串哈希

概念

这个东西很简单,字符串哈希是什么捏?和数字的哈希一样,字符串哈希就是把每一个字符串映射到一个数上去。具体来说,我们可以把一个字符串看成一个大进制数,比如 abc 我们就可以把它看成一个 26 进制的数字,那么这个数字就是 1×262+2×26+3。当然有的时候这个数字会很大,一般来说,我们会让它对一个大质数取余。所以我们就可以这样定义一个字符串的哈希函数 hash(str)=(i=0nid(stri)×baseni)modMod。函数 id(stri) 就是 stri 的编号,比如说你可以认为 a 的编号是 1 那么 id(a)=1base 是我们取的进制,一般取字符集大小,比如说小写字母就取 base=26,小写大写在一起就 base=52。但是有的时候所有字符都在一起,如果你很懒,你也可以直接让 base=137Mod 是一个相当大的质数。

这里有点需要注意:id 函数不能有 0 的值!为什么呢?举个例子,如果我们让 id(a)=0,id(b)=1,那么 abb 的哈希值就一样了。在这里 id=0 代表这一位是空的。

如果两个字符串的哈希值相同,我们也可以认为他们相同,但是很明显,这是有概率出错的。Mod 取大素数可以降低出错的概率,因为这个时候我们可以认为哈希值在 0Mod1 里均匀分布,所以冲突概率就是 1Mod1。如果 Mod 不是质数就没有均匀分布了,概率就不能这么算了。一般来讲哈希值用 long long 存,Mod 可以取成 1e9+7 或是 998244353。但是这个时候还有可能会冲突,所以我们可以搞两个模数,做算两次哈希,如果两次都一样,我们就可以认为这两个字符串一样。

有的时候我们不方便使用双模数,这个时候我们就可以用伟大的 __int128 弄个 1e18 级别的质数(比如 100000007998244353)


取子串哈希值

光是这样哈希看上去没有啥大用的样子,实际上如果我们算出来一个串的哈希值,我们也可以把它每一个前缀的哈希值给算出来,这很容易,我们记 fi 为到第 i 个字符的哈希值,fi=(fi1×base+id(stri))modMod=(j=0iid(strj)×baseij)。很容易理解。

那么如何取一个子串的哈希值呢?我们记这个子串是 strlr,它的哈希值就应该是 (i=lrid(stri))modMod×baseri=((frfl1×baserl+1)modMod+Mod))modMod,注意这里面 frfl1×baserl+1 可能是负数。


几道题目,我先不放,我以后一起放(

posted @   SIXIANG32  阅读(62)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2020-07-07 欢迎来到 SIXIANG 的 blog~
点击右上角即可分享
微信分享提示