Подтвердить что ты не робот

Поиск k наиболее распространенных слов в использовании файла - памяти

Скажем, вам дан огромный файл, скажем, 1 ГБ. Файл содержит слово в каждой строке (всего n слов), и вы хотите найти k наиболее частых терминов в файле.

Теперь, полагая, что у вас достаточно памяти для хранения этих слов, каков лучший способ подойти к вопросу с точки зрения сокращения использования памяти и постоянных накладных расходов в сложности Big-O? Я считаю, что можно использовать два основных алгоритма:

  • Используйте хеш-таблицу и мини-кучу для хранения вхождений и верхних K-слов. Это O (n + nlogk) ~ O (N)
  • Используйте trie для хранения слов и вхождений, а затем пересекайте trie для подсчета наиболее часто встречающихся слов. Это O (n * p) ~ O (N), где p - длина самого длинного слова.

Какой подход лучше?

Кроме того: если у вас недостаточно памяти для хэш-таблицы/trie (т.е. ограниченная память размером 10 МБ), то какой лучший подход?

4b9b3361

Ответ 1

Что более эффективно в отношении константы, очень зависимо. С одной стороны, trie предлагает строгую временную сложность O(N) для вставки всех элементов, тогда как хэш-таблица может упасть до квадрического времени в худшем случае. С другой стороны, попытки не очень эффективны, когда дело доходит до cache - каждый поиск требует O(|S|) запросы памяти произвольного доступа, что может привести к значительному снижению производительности.

Оба подхода действительны, и я думаю, что есть несколько соображений, которые следует принимать при выборе одного над другим, как максимум latency ( если это система реального времени), пропускная способность и время для разработки.

Если важна средняя производительность приложения, я бы предложил создать кучу файлов и выполнить статистический анализ какой подход лучше. Wilcoxon подписанный тест - это фактическое фактическое фактическое испытание гипотезы при использовании.


Что касается встроенных систем: оба подхода по-прежнему актуальны, но здесь: Каждый "Node" (или куча узлов) в trie будет на диске, а не на RAM. Обратите внимание, что это означает, что для диска произвольного доступа trie O (| S |) ищет для каждой записи, что может быть медленным.

Для хэш-решений у вас есть 10 МБ, скажем, они могут использовать 5 МБ из них для хэш-таблицы указателей на диск. Предположим также, что вы можете хранить 500 различных дисковых адресов на этих 5 МБ (пессимистический анализ здесь), это означает, что у вас осталось 5 МБ для загрузки ковша после каждого хеша, и если у вас есть 500 ковшей с коэффициентом нагрузки 0,5, это означает вы можете хранить 500 * 5 МБ * 0,5 ~ = 1,25 ГБ > 1 ГБ данных, таким образом, используя решение хеш-таблицы, поэтому с использованием хэширования - каждому поиску потребуется только O(1) случайный диск ищет, чтобы найдите ведро, содержащее соответствующую строку.

Обратите внимание, что если этого еще недостаточно, мы можем перерисовать таблицы указателей, очень похожие на то, что делается в таблице подкачки в механизм виртуальной памяти.

Из этого можно заключить, что для встроенных систем хеш-решение лучше для большинства случаев (обратите внимание, что он может по-прежнему страдать высокой задержкой в ​​худших случаях, здесь нет серебряной пули).


PS, дерево оснований обычно быстрее и компактнее, чем trie, но страдает от тех же побочных эффектов trie по сравнению с хэш-таблицами (хотя и менее значительными, конечно).

Ответ 2

Для параметра ограниченной памяти вы можете быстро отсортировать список сначала, а затем просто заполнить хэш-таблицу с помощью k элементов в ней. Затем вам понадобится еще один счетчик, чтобы узнать, сколько элементов находится в текущем слове, которое вы проверяли, - если оно выше, то вы заменяете самый нижний элемент в хеш-таблице на свой текущий элемент.

Это, вероятно, будет работать нормально для начального списка, но будет медленнее, чем просто сканирование полного списка и заполнение хэш-таблицы счетчиком.

Ответ 3

Вы управляете хранением промежуточных результатов? если true:

у вас может быть какая-то метаструктура. и набор хешируемых. Вы читаете часть данных (в то время как размер вашего хэша < 3 мб) и заполняете хеш-таблицу. а размеp > 3mb вы сохраняете на диске. если вы ограничены размером 10 мб хэш-таблицы, например, 3 мб.

метапримените свои хеш-таблицы. в мета вы можете хранить количество уникальных слов и количество всех слов в этом хэше и максимальное количество одного мира!!! я

после этого. вы можете загружать хеш-таблицы с диска и сливаться.

например, вы можете загружать хеш-таблицу в порядке возрастания уникальных слов или максимальное количество одного мира в хеше. на этом этапе вы можете использовать некоторые эвристики.