Способ хранения большого словаря с низким объемом памяти + быстрый поиск (на Android) - PullRequest
22 голосов
/ 17 февраля 2010

Я разрабатываю приложение для игры в слова для Android, для которого требуется большой (~ 250 000 словарь словаря) доступный. Мне нужно:

  • достаточно быстрые просмотры, например предпочтительнее постоянное время, иногда нужно выполнить 200 поисков в секунду, чтобы решить головоломку со словом, и, возможно, 20 поисков в течение 0,2 секунды чаще, чтобы проверить слова, которые только что написал пользователь.

РЕДАКТИРОВАТЬ: Поиски обычно спрашивают "Есть в словаре?". Я хотел бы также поддерживать до двух подстановочных знаков в слове, но это достаточно просто, просто сгенерировав все возможные буквы, которые могли быть подстановочными знаками, и проверив сгенерированные слова (т.е. 26 * 26 поисков для слова с двумя подстановочными знаками) .

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

В моих первых наивных попытках использовался Java-класс HashMap, что вызвало исключение нехватки памяти. Я рассмотрел использование баз данных SQL Lite, доступных на Android, но это выглядит как излишнее.

Какой хороший способ сделать то, что мне нужно?

Ответы [ 7 ]

18 голосов
/ 17 февраля 2010

Вы можете достичь своих целей также с более скромными подходами ... если это игра в слова, то я подозреваю, что вы используете 27 букв алфавита. Предположим, что алфавит состоит не более чем из 32 букв, то есть 5 битов на букву. Затем вы можете втиснуть 12 букв (12 x 5 = 60 бит) в одну Java long , используя 5-битное / буквенное тривиальное кодирование.

Это означает, что на самом деле, если у вас нет более длинных слов, чем 12 букв / слов, вы можете просто представить свой словарь как набор длинных слов Java. Если у вас есть 250 000 слов, простое представление этого набора в виде единого отсортированного массива длин должно занять 250 000 слов x 8 байт / слово = 2 000 000 ~ 2 МБ памяти. Тогда поиск выполняется с помощью бинарного поиска, который должен быть очень быстрым, учитывая небольшой размер набора данных (менее 20 сравнений, так как 2 ^ 20 приводит к более чем одному миллиону).

Если у вас есть более длинные слова, чем 12 букв, то I сохранит слова из> 12 букв в другом массиве, где 1 слово будет представлено 2 каскадными последовательностями Java очевидным образом.

ПРИМЕЧАНИЕ: причина, по которой это работает и, вероятно, более компактно, чем три и, по крайней мере, очень проста в реализации, состоит в том, что словарь постоянен ... деревья поиска хороши, если вам нужно изменить набор данных, но если набор данных постоянен, вы часто можете выполнить простой бинарный поиск.

3 голосов
/ 17 февраля 2010
3 голосов
/ 17 февраля 2010

Я предполагаю, что вы хотите проверить, принадлежит ли данное слово словарю.

Взгляните на фильтр Блума .

Фильтр Блума может выполнять запросы типа «принадлежит ли Х предопределенному набору» с очень маленькими требованиями к хранилищу. Если ответ на запрос «да», он имеет небольшую (и настраиваемую) вероятность быть неправильным, если ответ на запрос «нет», то ответ гарантированно будет правильным.

Согласно статье в Википедии, вам может потребоваться менее 4 МБ места для вашего словаря из 250 000 слов с вероятностью ошибки 1%.

Фильтр Блума правильно ответит «находится в словаре», если слово фактически содержится в словаре. Если в словаре нет слова, фильтр Блума может дать ложный ответ «находится в словаре» с небольшой вероятностью.

0 голосов
/ 07 августа 2016

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

0 голосов
/ 18 марта 2010

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

0 голосов
/ 17 февраля 2010

Вы также можете использовать Android NDK и выполнять структуру на C или C ++.

0 голосов
/ 17 февраля 2010

Вам понадобится какой-то три .Возможно, троичный поиск был бы хорош, я думаю.Они дают очень быстрый поиск и низкое использование памяти. Эта статья дает дополнительную информацию о TST.Это также говорит о сортировке, поэтому не все это будет применяться. Эта статья может быть немного более применимой.Как говорится в статье, TST

объединяет временную эффективность цифровых попыток с пространственной эффективностью двоичных деревьев поиска.

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

...