映射
哈希算法广义来看是将一个难以表示的信息(比如字符串)和一个容易表示的信息(比如数字)建立一种映射关系。
这种映射通常不是普通的一一对应的映射(比如双射),因为这样映射的难度比较大。
比如,给定
所以哈希通常是牺牲了双射的严谨性,来保证映射容易实现。
即找一个容易实现的映射,构造一个大概率一对一,小概率多对一(从左到右映射一般不会一对多)的映射集合。
这样的想法称为哈希。
通常情况下,哈希的冲突(多对一)的概率很小。
但是要解决也有一些办法:
一种是用多种哈希方式,在每种哈希方式都一一映射的时候才成立
另一种是建立哈希表,每个映射后的值为表头,内存着多个原数值
字符串哈希
一般字符串哈希是一种将字符串映射成数字的方式,最常用的是进制法
即将整个字符串看作一个
比如可以将
(将
设
其中
然而这样数字通常会很大,存不下,好办法是给数字取模,这样就会导致有的不同数字取完模变成一样的数字。
没事,我们假装这种情况不存在,然后做完了(目移)
好吧,为了减小冲突的概率,要尽量大质数作为模数。
大是为了让值域尽可能大,减小冲突概率。
选用质数
比如选用了
而如果
将字符串映射到数字后,就可以实现
查询哈希子串:
假设我们有整个字符串
先截取
多出的部分是
所以
令
拼接子串:
将字符串
设字符串
则
有了拼接和拆分的方法,字符串哈希疑似就能上线段树了捏(事实上也能)
应用
字符串匹配
基本应用,判断两个字符串的哈希值是否相同
判断回文
对字符串正着做一遍,反着做一遍,判断正反是否相同
最长公共前缀
先分别求两个字符串的哈希值
对前缀长度二分答案,然后用哈希判断
最长公共子串
先二分答案,将第一个串所有长度为二分值的子串的哈希值存在桶里
然后再枚举第二个串所有长度为二分值的答案,判断桶里是否存在。
练习题
1458:Seek the Name, Seek the Fame
P2757 [国家集训队] 等差子序列 需要线段树