问题
Pi = 3.14159 26 5358979323846 26 433... 所以要重复的第一个 2 位子串是 26。
找到要重复的前 20 位子字符串的有效方法是什么?
约束
我有大约 500 GB 的 Pi 数字(每个数字 1 个字节),以及大约 500 GB 的可用磁盘空间。
我有大约 5 GB 的可用 RAM。
我对一种适用于任意序列而不是 Pi 本身的特定答案的有效算法感兴趣。换句话说,我对“print 123....456”形式的解决方案不感兴趣,即使它打印的数字是正确的。
我试过的
我将每个子字符串放入一个哈希表并报告第一次冲突。
(哈希表被构造为一个有序链表的数组。数组的索引由字符串的底部数字给出(转换为整数),每个节点中存储的值是 Pi 展开中的位置子字符串第一次出现的地方。)
在我用完 RAM 之前,这一直很好。
为了扩展到更长的序列,我考虑过:
为从某个范围开始的所有子字符串生成哈希,然后继续搜索剩余的数字。这需要为每个范围重新扫描整个 Pi 序列,因此变为 N^2 阶
Bucket 将这组 20 位子串排序到多个文件中,然后使用哈希表分别在每个文件中查找第一个重复项。不幸的是,使用这种方法,我的磁盘空间不足,因此需要 20 次遍历数据。(如果我从 1000 位数字开始,那么我将得到 1000 个 20 位数字的子字符串。)
每个字节存储 2 位 Pi 以释放更多内存。
将基于磁盘的后备存储添加到我的哈希表中。我担心这会表现得很糟糕,因为没有明显的参考位置。
有更好的方法吗?
更新
我尝试了 Adrian McCarthy 的 qsort 方法,但这似乎比散列查找重复项要慢一些
我查看了 btilly 的 MapReduce 关于并行化算法的建议,但它在我的单台计算机上受大量 IO 限制,因此不适合我(使用我的单磁盘驱动器)
昨晚我实现了 supercat 的方法来拆分文件并在前 180 亿位中搜索 19 位子字符串。
这找到了 16 个匹配项,所以我使用 Jarred 的建议重新检查 19 位匹配项以找到第一个 20 位匹配项
搜索 180 亿位数字需要 3 小时来拆分文件,然后需要 40 分钟才能重新扫描文件以查找匹配项。
回答
20 位子串 84756845106452435773 位于 Pi 的十进制扩展中的位置 1,549,4062,637 和 17,601,613,330。
非常感谢大家!