Вычисление минимального расстояния Хэмминга между струной и набором струн

Пример: если у меня есть строка «asdf» и набор строк («qwer», «aswr», «asdv»). Расстояние Хэмминга между набором и строкой будет равно 1, поскольку "asdv" и "asdf" имеют расстояние Хэмминга, равное единице.

Легко использовать грубую силу с чем-то вроде этого

def hamming_distance(string, set):
    min = len(string)
    for element in set:
        element_distance = sum(ch1 != ch2 for ch1, ch2 in zip(string, element))
        if min > element_distance:
            min = element_distance
        if min == 0:
            break
    return min

Я думаю, что это O (n * k), где n = len (строка) и k = len (набор). Однако максимальный размер набора масштабируется с n ^ 2, что означает, что мы, по сути, имеем дело с O (n ^ 3). Наборы довольно статичны, поэтому, если предварительная обработка поможет, это определенно вариант.

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


person blackfedora    schedule 09.01.2014    source источник


Ответы (1)


Во-первых, расстояние Хэмминга между строками — это метрика. Таким образом, вы пытаетесь найти k ближайших соседей в метрическом пространстве (где k = 1).

Следовательно, вы можете рассмотреть дерево, подобное структуре данных M-Tree: (см. http://en.wikipedia.org/wiki/M-tree и http://www.vldb.org/conf/1997/P426.PDF). Это дерево предназначено для уменьшения числа сравнений расстояний, которые необходимо выполнить для поиска «ближайших соседей».

Лично я не смог найти реализацию M-Tree в Интернете, которая бы меня удовлетворила (см. мой закрытый поток Поиск зрелой реализации M-Tree), поэтому я накатил свою собственную.

Моя реализация находится здесь: https://github.com/jon1van/MTreeMapRepo

ЕДИНСТВЕННАЯ другая реализация, которую я смог найти, была следующей: https://github.com/erdavila/M-Tree Мне не понравилась эта реализация, потому что в ней не было функции удаления (и некоторых других проблем) (но она была бесплатной, так что... это хорошо).

Вы можете рассмотреть возможность использования моего кода (который решает поиск kNN в общем метрическом пространстве) с метрикой расстояния Левенштейна (http://en.wikipedia.org/wiki/Levenshtein_distance). Найти полностью реализованную метрику расстояния Левенштейна в Интернете должно быть довольно легко.

Добавлена ​​функция расстояния Левенштейна** http://code.google.com/p/google-refine/source/browse/trunk/src/main/java/edu/mit/simile/vicino/distances/LevensteinDistance.java?r=181

person Ivan    schedule 09.01.2014
comment
М-дерево — отличный способ быстро пропустить большинство элементов набора. Мне придется немного поиграть с ним, чтобы увидеть, разумна ли пространственная сложность, но это выглядит действительно многообещающе. Я обязательно приму ваш ответ, если все пойдет хорошо. - person blackfedora; 09.01.2014