你说得对,但我几乎从来不把哈希叫做哈希,我习惯了叫 Hash。
比赛链接:https://vjudge.net/contest/766880。
卡 Hash 的出题人都是毒瘤出题人喵!一点也不良心。
A - Barn Echoes G
由于这个长度只有 \(80\),因此随便枚举然后 Hash 判断一下就可以了。甚至都可以不用 Hash,直接判断,但是出于对这道题目的尊重我还是使用了 Hash,为了练习嘛。
B - 字符串哈希
Hash 板题。对每个字符串进行 Hash 然后丢进 map 判断或者数组排序去重,取 size 什么的即可。
C - 阅读理解
卡 map 不好玩。
开 \(n\) 个 set,针对每篇文章把它所出现的字符串 Hash 之后丢进去,查找的时候枚举每篇文章然后在对应的 set 里面 count 就可以啦。
所以为什么要卡 map 呢。
D - 倒排索引
比较暴力的一个题,首先去枚举那个查询词 \(q\) 的所有拆出来的子串,Hash 后丢进 map 里标记上。接着枚举每个单词然后挨个去跑,装上了 map 里有的就增加答案就行了。
E - Colliding Encoding
按照他那个也许错误的神秘映射方法算出一个“Hash”值,然后再用正常的 Hash 再算一个,扔 map 里匹配即可。注意他那里边是有 \(0\) 的,如果作为开头可能会误判,考虑每个串前面加个 \(1\) 或者别的数,这样所谓前导零就能看得到了。
F - 于是他错误的点名开始了
随便 Hash,丢 map 里算个数就好了。
G - 匹配统计
顺着做一个 Hash,反过来做一个 Hash,以便求正着或者反着的区间 Hash 值。然后二分找,Hash 截取判相等,就可以啦!
H - ABB
你说得对,但我真的很想用 KMP 水掉这题。
和上一题一样的套路,不过这里判的是回文,且最后的答案需要推一个简单的小公式。以及注意回文长度,偶数和奇数是两种不同的情况喔!
I - 积木小赛
一开始几乎就是,一个双指针的套路,枚举 Bob 的情况然后指针跑去找 Alice 行不行得通。那么 Hash 用在哪了呢?就是最后的判重啦!不过,这里不能用 map,会被卡 /ll 所以我们只能使用排序去重,或者是 umap 等别的速度快些的东西。
J - ANT-Antisymmetry
异式的判回文,不过原理是一样的。和 G 类似,正反两遍 Hash,不过这里需要选择一遍(正反均可)做“反 Hash”——说人话就是,\(0\) 当做 \(1\) 去压,\(1\) 当做 \(0\) 去压。与 G 不同的是,这里肯定是偶数,不信你可以自己试试看,举出反例算我输!其实我已经把这个东西证明了,但是不想写,所以你无论如何都写不出反例的!
K - Censoring S
把 Hash 情况扔栈里做类似模拟的操作,去模拟这个过程,一删就删一大把,衔接算 Hash 的时候要删掉首位加上末位。记录一下哪些位置没删,遍历输出即可。
Hash 总结
Hash 是一个非常方便好用的字符串算法,多用于字符串比较、字符串匹配类型的题目。它可以将字符串的 \(O(len)\) 操作通过预处理降到 \(O(1)\),高效又简洁。但是其正确性无法做到严格保障,虽然说概率通常不高,但是也不能排除出现 Hash 冲突的情况——这个时候,你可以选择更大更保险更冷门的模数(选冷门是因为怕有人对着常用模数卡),或者多做几个不同的 Hash 给正确性套上多层保障,甚至有时候需要上随机数 Hash 这类玄学东西。总而言之,Hash 是一个很赞的字符串算法哟!
说这么多,你不是照样没在 25 S 考场上给 C 打 Hash 的暴力。
Thanks reading.