各位毒瘤大家好, 最近模拟赛考了一道trie+主席树好题, 但大家都用hash水过了这道题(包括我), 为了测试一下新搭建的HEAT OJ的hack功能, 我将继续扮演毒瘤的角色, 用毒瘤的艺术形象努力创造一个正能量的形象, 文体两开花, 弘扬中华文化, 右转去BZOJ搞了一晚上hashkiller, 回来卡了单哈希(双哈希是真滴卡不住

哈希(hash) :

利用大质数或其他对应函数把字符串转为一个正整数来快速判断字符串相等

通常可以模一个大质数或使用自然溢出

实现(例);

const int P = 1e9+7;
const int di = 1331;
hash[i] = (hash[i-1] * base + s[i]) % P;

其中\(base\), 我称之为底数, P我称之为模数, 事实上自然溢出相当于模了\(2^{64}\)

卡哈希的思想:

  1. 数学构造
  2. 随机数据(依据生日悖论

Part 1 生日悖论:

如果一个班级有23个人, 那么其中有两个人生日相同的概率超过50%

surprise 这与大部分人的直觉相违背, 所以称之为生日悖论

为什么会这样呢, 是自己的直觉不靠谱吗?

不, 我们可以考虑另一个问题, 如果一个班里有23人包括自己, 有人生日和自己相同的概率是多少?

没错, 大概为\(6%\)左右, 这是与直觉近似的, 其实我们的直觉正是把"有人生日相同"和"有人生日和自己相同"的概念相混, 实际有人生日和自己相同的概率确实很小

证明可以用排列组合开心的手玩一下

性质:

样本容量为\(n\), 超过\(50%\)概率有两个样本相同的概率为

\[1.18\sqrt{n}
\]

Part 2 卡大质数hash (1000000009) :

考虑生日攻击, 随机一个1e5大小的字符串, 询问长度为\(L\)的本质不同子串有多少个, 用大质数\(hash\)和后缀数组(也可以用自然溢出\(hash\))对拍, 输出不同子串的终止位置, 拿\(fc\)命令对比一下, 找出\(hash\)值相等的不同子串

正确性如生日悖论, 大概有超过\(50%\)的几率成功, 实际上质数不强的时候有很多相同

Part 3 卡自然溢出hash:

自然溢出\(hash\)在数据随机的情况下正确性极高, 因为它的值域很大, 很难生日攻击

考虑特殊构造:

对于底数为偶数:

构造\(aaaa\cdots aaaa\) 和 \(baaa\cdots aaaa\)两个长度相等且长度大于64的串

底数的六十四次方以上模\(P\)就会为零, \(b\)和\(a\)也会被判为相等

对于底数为奇数:

不太好卡, 要用神仙的构造方法:

设一个串\(s[]\), \(s[1] = 'a'\) 设$ |s| = strlen(s + 1)$ 为\(s\)的长度

定义$ (!s)$ 为\(s\)中的字符全部\('a'变'b', 'b'变'a',\) 当然\(s\)中只含有\('a'\)和\('b'\)两种字符

定义串\(S1 + S2\)为\(S1\)串在前\(S2\)串在后拼接起来, \(hash(s1)\) 为\(s1\)的哈希值

类似数列的, 我们定义一个"字符串列", 为一个字符串集合{\(S_n\)}, 后一个字符串可以通过前一个字符串推出

\(S_1 = "a"\)

\[S_i = S_{i-1} + (!S_{i-1})
\]

则\(S_i\)的长度为\(2^{i-1}\)

\[hash(S_i) = hash(S_{i-1}) * base^{|S_{i-1}|} + hash((!S_{i-1})) \\
= hash(S_{i-1}) * base^{2^{i-2}} + hash((!S_{i-1})) \\
hash((!S_{i-1})) = hash((!S_{i-2})) * base^{2^{i-2}} + hash(S_{i-1}) \\
hash(S_i) - hash((!S_{i-1})) = (hash(S_{i-1}) - hash((!S_{i-2}))) * base^{2^{i-2}} - (hash(S_{i-1}) - hash((!S_{i-2})))\\
hash(S_i) - hash((!S_{i-1})) = (hash(S_{i-1}) - hash((!S_{i-2}))) * (base^{2^{i-2}} - 1)
\]

希望得到 \(2^{64} | hash(S_i) - hash(!S_i)\) 设\(g_i = hash(S_i) - hash(!S_i)\)

\(g_i=g_{i-1}*(base^{2^{i-2}}-1)\) 每个 \((base^{2^{i-2}}-1)\) 都是偶数, 这使得g到第64项就就可以卡掉hash了,

但事实上12位以上就行, 因为

\[base^{2^{i-1}}-1=(base^{2^{i-2}}-1)*(base^{2^{i-2}}+1)
\]

为一个偶数乘一个偶数, 而左边的可以继续递归下去, 所以原式整除\(2^i\) 然后就结束啦

长大后, 我要当毒瘤, 爷爷奶奶可高兴了, 给我爱吃的...


毒瘤养成记1: 如何卡hash的更多相关文章

  1. 2016级算法第六次上机-F.AlvinZH的学霸养成记VI

    1082 AlvinZH的学霸养成记VI 思路 难题,凸包. 分析问题,平面上给出两类点,问能否用一条直线将二者分离. 首先应该联想到这是一个凸包问题,分别计算两类点的凸包,如果存在符合题意的直线,那 ...

  2. 2016级算法第六次上机-D.AlvinZH的学霸养成记V

    1081 AlvinZH的学霸养成记V 思路 中等题,计算几何. 这是一个排序问题,按极角排序.可以转化为叉积的应用,对于点A和B,通过叉积可以判断角度大小,共线时再判断距离. 叉积的应用.OA × ...

  3. 2016级算法第六次上机-C.AlvinZH的学霸养成记II

    1032 AlvinZH的学霸养成记II 思路 中等题,贪心. 所有课程按照DDL的大小来排序. 维护一个当前时间curTime,初始为0. 遍历课程,curTime加上此课程持续时间d,如果这时cu ...

  4. 2016级算法第五次上机-E.AlvinZH的学霸养成记IV

    1039 AlvinZH的学霸养成记IV 思路 难题,最大二分图匹配. 难点在于如何转化问题,n对n,一个只能攻击一个,判断是否存在一种攻击方案我方不死团灭对方.可以想到把所有随从看作点,对于可攻击的 ...

  5. 2016级算法第五次上机-D.AlvinZH的学霸养成记III

    850 AlvinZH的学霸养成记III 思路 难题.概率DP. 第一种思考方式:直接DP dp[i]:从已经有i个学霸到所有人变成学霸的期望. 那么答案为dp[1],需要从后往前逆推.对于某一天,有 ...

  6. nlp算法工程师养成记 目标要求

    时间规定: 2018.12.07-2018.02.15 能力养成: linux, shell python, c++(会多少算多少) tensorflow, keras, pytorch(tf优先) ...

  7. 架构师养成记--35.redis集群搭建

    前记:redis哨兵经验之谈.哨兵做主从切换可能要花费一两秒,这一两秒可能会丢失很多数据.解决方法之一是在java代码中做控制,try catch 到 链接断开的异常就sleep 一两秒钟再conti ...

  8. 架构师养成记--31.Redis的几种类型

    String类型 Redis一共分为五种基本数据类型:String.Hash.List.Set.ZSet String类型是包含很多张类型的特殊类型,并且是二进制安全的.比如对序列化的对象进行存储,比 ...

  9. 架构师养成记--15.Disruptor并发框架

    一.概述 disruptor对于处理并发任务很擅长,曾有人测过,一个线程里1s内可以处理六百万个订单,性能相当感人. 这个框架的结构大概是:数据生产端 --> 缓存 --> 消费端 缓存中 ...

随机推荐

  1. linux 字符设备注册

    如我们提过的, 内核在内部使用类型 struct cdev 的结构来代表字符设备. 在内核调用你 的设备操作前, 你编写分配并注册一个或几个这些结构. [11] 11为此, 你的代码应当包含 < ...

  2. 深度解读 - TDD详细(测试驱动开发)

    本文结构: 什么是 TDD 为什么要 TDD 怎么 TDD FAQ 学习路径 延伸阅读 什么是 TDD TDD 有广义和狭义之分,常说的是狭义的 TDD,也就是 UTDD(Unit Test Driv ...

  3. 2019-3-8-为何使用-DirectComposition

    title author date CreateTime categories 为何使用 DirectComposition lindexi 2019-3-8 8:56:9 +0800 2018-04 ...

  4. vue-learning:23 - js - leftcycle hooks

    vue 生命周期钩子函数 每一个Vue实例在创建时都需要经过一系列初始化.根据vue实例化过程中执行的逻辑,可以分为5个阶段: 初始化阶段 模板编译阶段 虚拟DOM挂载阶段 响应更新阶段 卸载阶段 这 ...

  5. dotnet 通过 WMI 获取系统安装的驱动

    本文告诉大家如何通过 WMI 获取用户已经安装的驱动程序 通过 Win32_SystemDriver 可以获取用户已经安装的驱动程序 var mc = "Win32_SystemDriver ...

  6. python 下载bilibili视频

    说明: 1.清晰度的选择要登录,暂时还没做,目前下载的视频清晰度都是默认的480P 2.进度条仿linux的,参考了一些博客修改了下,侵删 3.其他评论,弹幕之类的相关爬虫代码放在了https://g ...

  7. Microsoft Edge 离线安装包下载

    Microsoft Edge 现已准备就绪 下一版 Microsoft Edge 已准备好进行企业评估. 立即下载离线安装程序.查看管理策略并尝试 Internet Explorer 模式. http ...

  8. 13.python基础试题(二)

    借鉴:https://www.cnblogs.com/shengyang17/p/8543712.html https://www.cnblogs.com/you-wei1/p/9693254.htm ...

  9. .NETCore3.1中的Json互操作最全解读-收藏级

    前言 本文比较长,我建议大家先点赞.收藏后慢慢阅读,点赞再看,形成习惯! 我很高兴,.NETCore终于来到了3.1LTS版本,并且将支持3年,我们也准备让部分业务迁移到3.1上面,不过很快我们就遇到 ...

  10. 深入ReentrantLock的实现原理和源码分析

    ReentrantLock是Java并发包中提供的一个可重入的互斥锁.ReentrantLock和synchronized在基本用法,行为语义上都是类似的,同样都具有可重入性.只不过相比原生的Sync ...