Проблема
Pi = 3.14159 26 5358979323846 26 433... поэтому первая 2-значная подстрока для повторения составляет 26.
Что такое эффективный способ поиска первой 20-значной подстроки?
Ограничения
-
У меня около 500 гигабайт цифр Pi (1 байт на цифру) и около 500 гигабайт свободного места на диске.
-
У меня около 5 гигабайт свободной памяти.
-
Меня интересует эффективный алгоритм, который будет работать для произвольных последовательностей, а не для конкретного ответа для самого Pi. Другими словами, меня не интересует решение формы "print 123.... 456", даже если номер, который он печатает, верен.
Что я пробовал
Я помещаю каждую подстроку в хеш-таблицу и сообщаю о первом столкновении.
(Хэш-таблица построена как массив отсортированных связанных списков. Индекс в массив задается нижними цифрами строки (преобразуется в целое число), а значение, хранящееся в каждом node, является местоположением в разложении Pi, где впервые появилась подстрока.)
Это работало нормально, пока я не закончил RAM.
Чтобы масштабировать до более длинных последовательностей, я рассмотрел:
-
Генерация хэша для всех подстрок, начинающихся в определенном диапазоне, а затем продолжения поиска по остальной части цифр. Это необходимо для повторной проверки всей последовательности Pi для каждого диапазона, поэтому порядок N ^ 2
-
Ведро сортирует набор 20-значных подстрок для нескольких файлов, а затем использует хеш-таблицу для поиска первого повтора в каждом файле отдельно. К сожалению, с этим методом у меня заканчивается дисковое пространство, поэтому потребуется 20 проходов через данные. (Если я начну с 1000 цифр, то в итоге я получу 1000 20-значных подстрок.)
-
Сохранение 2 цифр Pi на байт, чтобы освободить больше памяти.
-
Добавление дискового хранилища на основе диска в мою хеш-таблицу. Я беспокоюсь, что это будет вести себя очень плохо, поскольку нет очевидной локальности ссылок.
Есть ли лучший подход?
Update
-
Я пробовал метод qsort от Adrian McCarthy, но это показалось немного медленнее, чем хэширование для поиска дубликатов.
-
Я посмотрел на предложение Btilly MapReduce для параллелизации алгоритма, но он был сильно привязан к IO на моем одном компьютере, поэтому мне не подходит (с моим единственным диском)
-
Я реализовал метод supercat, который потратил прошлой ночью на разделение файлов и поиск 19-значных подстрок в первые 18 миллиардов цифр.
-
Это нашло 16 совпадений, поэтому я использовал предложение Jarred, чтобы переустановить 19-разрядные совпадения, чтобы найти первые 20-значные совпадения
Чтобы выполнить поиск 18 миллиардов цифр 3 часа для разделения файлов и 40 минут для повторного сканирования файлов, ищущих совпадения.
Ответ
20-значная подстрока 84756845106452435773 находится в позициях 1,549,4062,637 и 17,601,613,330 в десятичном разложении Pi.
Большое спасибо всем!