2009-11-02 3 views
4

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

У меня есть плоский файл случайных (английских) слов, один на каждый линия. Мне нужно написать эффективную программу для подсчета количества вхождений каждого слова. Файл большой (возможно, около 1 ГБ), но у меня много памяти для всего. Они хранятся на постоянном носителе, поэтому скорость чтения медленная, поэтому мне нужно просто прочесть ее один раз линейно.

Мои две идеи о том, чтобы использовать хэш со словами => нет. вхождениях или trie с no. появления в конечном узле. У меня достаточно ОЗУ для хэш-массива, но я думаю, что trie будет иметь быстрый или быстрый поиск.

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

+0

KISS. В любом случае доступ к структуре данных должен быть * справедливым * прозрачным. – 2009-11-02 20:33:46

ответ

2

Я думаю, что трю со счетом как листья может быть быстрее.

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

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

Например, если вы читали персонажей: «torto», trie знал бы, что единственно возможным словом, которое начинается таким путем, является черепаха.

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

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

2

Я бы использовал объект Dictionary, в котором ключ преобразуется в нижний регистр, а значение - это счетчик. Если словарь не содержит слова, добавьте его со значением 1. Если оно содержит слово, увеличьте значение.

+0

Предполагая, что он использует .net, да, это было бы хорошо. –

+0

Это не словарь только хеш-таблицы? Я не использую .NET btw. – erjiang

0

простой питон скрипт:

import collections 
f = file('words.txt') 
counts = collections.defaultdict(int) 
for line in f: 
    counts[line.strip()] +=1 

print "\n".join("%s: %d" % (word, count) for (word, count) in counts.iteritems()) 
+0

ОП запрашивает алгоритм, и вы дали ему код? – TStamper

+0

ах справа. Если бы это был python, использование hash builtins было бы быстрее, чем trie, поскольку он использовал собственный код. – zzzeek

+0

также hash is O (1) в любом случае ... – zzzeek

1

Я думаю, что Trie является излишеством для использования. Хеш слова => вхождения - это именно то, что я буду использовать. Даже используя медленный интерпретируемый язык, такой как Perl, вы можете разбить 1GB-файл таким образом всего за несколько минут. (Я сделал это раньше.)

1

У меня достаточно ОЗУ для хэш-массива, но я думаю, что у trie будет быстрый или быстрый поиск.

Сколько раз будет выполняться этот код? Если вы просто делаете это один раз, я бы сказал, что оптимизируйте свое время, а не время вашего процессора, и просто делайте то, что быстрее всего реализуется (в разумных пределах). Если у вас есть стандартная функция библиотеки, которая реализует интерфейс с ключом, просто используйте это.

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

2

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

2

Хэш-таблица (если все сделано правильно, и вы сказали, что у вас много ОЗУ) O (1) для подсчета определенного слова, тогда как trie будет O (n), где n - длина слово.

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

+0

В зависимости от алгоритма хэширования хэш также может быть O (n). Или лучше, или хуже. – Annabelle

+0

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

+0

Как они сказали, вам придется, по крайней мере, просканировать линейное слово, чтобы хэшировать его или пересечь с ним, так что была бы операция O (n) в любом случае. – erjiang

0

Использование Python!

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

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

Смежные вопросы