Задача обработать файл содержащий N слов. Суть решения заключается в использовании внешней сортировки. Данные обрабатываются в 3 прохода:
- Из исходного файла читает по X слов, переводим их в нижний регистр, сортируем сегмент встроенными средствами и записываем сортированные сегменты во временные файлы с суффиксом '.0' (0.0, 1.0, 2.0, etc.) по X слов в каждом файле. Где X << N. На этом шаге нужно O(X) памяти и O(N) времени. Вообще O(N * X * log(X)), но X константа, поэтому O(N).
- Используюя идею merge sort: берем по два временных файла сгенерированных на предыдущем шаге (например 0.0 и 1.0) и сливаем их в файл с именем с суффиксом '.1' (например 0.1). Проделываем операцию пока не кончатся файлы с суффиксом '.0'. Повторяем этот шаг в обратную сторону: мержим по два файла с суффиксом '.1', в один файл c суффиксом '.0'. Повторяем шаг пока не останется один файл. На этом шаге нужно O(1) памяти (только под два слова, по одному из каждого сливаемого файла) и O(N * log(N)) времени, так как этот шаг нужно повторить log(N/X) раз. Но нужно 2 * N дополнительной памяти на диске под временные файлы.
- В полученном отсортированном файле легко посчитать количество слов в один проход. O(1) памяти, O(N) времени.
Итого получаем алгоритм работающий за O(N*log(N)) времени и требующий O(1) оперативной памяти и 2 * N памяти на диске.
"Война и Мир" на английском языке содержит ~570000 слов. На компьютере AMD FX-8320 c HDD обработка этого файла занимает 1m40s и укладывается в ~500+300кБайт оперативной памяти (500кБайт уже выделенно скрипту перед началом обработки).