"Несколько миллионов" для современных объемов оперативной памяти -- это не проблема. Имеет смысл уточнить ограничения, накладываемые на вашу программу. Вы пробовали решить ее "в лоб"? Не занимаетесь ли вы преждевременной оптимизацией? :)
Если объем входного текста действительно не ограничен сверху, тогда это задача выглядит, например, как один из класссических примеров map-reduce (я ни в коем случае не о фреймворках, хадупах и прочих зукиперах, а об идее), которая сводится к тому, чтобы разбить входной поток на N фрагментов фиксированного размера (например, по миллиону строк), посчитать количество слов в каждом фрагменте независимо (шаг map), получив на выходе N наборов ключ-значение (где, ключ -- слово, значение -- число вхождений), далее просуммировать эти наборы (шаг reduce). Если число ключей на выходе map опять же огромно (что я себе представляю с трудом для "натуральных" языков), можно шардить промежуточные результаты, когда шаг map на выходе выдает не один сплошной файл, а K фрагментов (например, первый -- слова на "a-c", второй -- на "d-f" и т.д.). Здесь немного подробнее об этом:
michaelnielsen.org/blog/write-your-first-mapreduce...