Структура данных для нахождения соседних ключей с подобными битовыми значениями

Это почти ортогональные проблемы. shared_ptr не играет никакой роли в распределении объектов.

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

10
задан SPWorley 10 June 2009 в 18:27
поделиться

13 ответов

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

BK-деревья обычно описываются со ссылкой на текст и с использованием расстояния Левенштейна для построения дерева, но его просто написать в терминах двоичных строк и расстояние Хэмминга.

5
ответ дан 3 December 2019 в 23:51
поделиться

Если вас устраивает рандомизированный алгоритм (в данном случае Монте-Карло), вы можете использовать minhash .

0
ответ дан 3 December 2019 в 23:51
поделиться

Я бы выбрал инвертированный индекс , как поисковая машина. У вас фиксированный словарный запас из 64 слов. Затем сходство измеряется расстоянием Хэмминга, а не косинусом сходства, которое может использовать поисковая система. Построение индекса будет медленным, но вы должны иметь возможность запрашивать его с нормальной скоростью поисковой системы.

Книга Введение в поиск информации описывает эффективное построение, хранение, сжатие и запросы инвертированных индексов. .

1
ответ дан 3 December 2019 в 23:51
поделиться

Я не до конца обдумал это, но у меня есть идея, с чего бы начать.

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

0
ответ дан 3 December 2019 в 23:51
поделиться

Создайте двоичное дерево (в частности, trie ), представляющее каждый ключ в вашем start устанавливается следующим образом: корневой узел - это пустое слово, при перемещении вниз по дереву влево добавляется 0, а при перемещении вниз вправо - 1.

3
ответ дан 3 December 2019 в 23:51
поделиться

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

A xor B

Чтобы найти разность битов, затем подсчитайте результат, используя метод вроде this .

Это фактически дает вам расстояние Хэмминга.

Так как это может быть сведено к десяткам инструкций на тест, это может работать довольно быстро.

0
ответ дан 3 December 2019 в 23:51
поделиться

«Почти оптимальные алгоритмы хеширования для приближенного ближайшего соседа в больших измерениях» , от 2008 года, кажется лучшим результатом на тот момент. Я не буду пытаться резюмировать, так как прочитал это более года назад, и это непросто. Это со страницы хеширования с учетом локальности вместе с реализацией более ранней версии схемы. Более общие указатели можно найти в поиске ближайшего соседа .

Этот вопрос задавался раньше: Самый быстрый способ найти строку, наиболее похожую на входную?

1
ответ дан 3 December 2019 в 23:51
поделиться

База данных / структура может быть препроцессируется как сколько угодно

Ну ... ЕСЛИ это правда. Тогда все, что вам нужно, это матрица сходства ваших расстояний Хэмминга. Сделайте матрицу разреженной, обрезав большие расстояния. Он не становится быстрее и не так сильно требует памяти.

1
ответ дан 3 December 2019 в 23:51
поделиться

Похоже, это хорошо подходит для S-Tree, которое похоже на иерархический инвертированный файл. Хорошие ресурсы по этой теме включают следующие документы:

Иерархический растровый индекс: эффективный и масштабируемый метод индексирования для атрибутов с множеством значений.

Улучшенные методы построения дерева подписей (2000)

Цитата из первого :

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

Эти статьи включают ссылки на другие исследования, которые могут оказаться полезными, например, M-Trees .

3
ответ дан 3 December 2019 в 23:51
поделиться

Ну, вы можете вставить все соседние ключи вместе с исходным ключом. Это означало бы, что вы храните (64 выбирают k) раз больше данных для k разных битов, и вам потребуется заранее решить k. Хотя вы всегда можете расширить k с помощью грубой силы, запрашивая соседей, и это автоматически запросит соседей ваших соседей, которые вы вставили. Это также дает вам компромисс между пространством и временем: например, если вы принимаете 64-кратное увеличение объема данных и в 64 раза медленнее, вы можете получить два бита расстояния.

0
ответ дан 3 December 2019 в 23:51
поделиться

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

-1
ответ дан 3 December 2019 в 23:51
поделиться
0
ответ дан 3 December 2019 в 23:51
поделиться

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

One_Try()
    1. Generate randomly a 20-bit subset S of 64 bits
    2. Ask for a list of elements that agree with test on S (about 2^10 elements)
    3. Sort that list by Hamming distance from test 
    4. Discard the part of list after cutoff

Вы повторяете One_Try столько, сколько вам нужно, при объединении списков. Чем больше у вас будет попыток, тем больше очков вы наберете. Например, если x находится в пределах 5 бит, вы найдете его за одну попытку с вероятностью примерно (2/3) ^ 5 = 13%. Поэтому, если вы повторите 100 попыток, вы найдете все, кроме примерно 10 ^ {- 6} таких x . Общее время: 100 * (1000 * log 1000) .

Основным преимуществом этого является то, что вы можете выводить ответы на вопрос 2 по мере продвижения, поскольку после первых нескольких попыток вы '

0
ответ дан 3 December 2019 в 23:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: