Преобразование N строк в общую целевую строку максимум за K правок

У меня есть набор строк [S1 S2 S3 ... Sn] и я считаю все такие целевые строки T так что каждый из S1 S2... Sn может быть преобразован в T в общей сложности K редактирует.
Все строки имеют фиксированную длину L и редактирование здесь - расстояние Хэмминга.

Все, что я имею, - это своего рода грубая сила. Итак, если мой размер алфавита равен 4, у меня есть пробное пространство O(4^L) и требуется O(L) время, чтобы проверить каждый из них. Я не могу снизить сложность от экспоненциальной до некоторой поли или псевдополия! Есть ли способ сократить пространство для образца, чтобы сделать лучше?

Я попытался визуализировать это как в L-мерном векторном пространстве. Мне дали N баллов, и я должен подсчитать все баллы, у которых сумма расстояний от указанных N баллов меньше или равна K.
i.e. d1 + d2 + d3 +...+ dN <= K
Есть какой-нибудь известный геометрический алгоритм, который решает эту или аналогичную проблему с большей сложностью? Пожалуйста, укажите мне в правильном направлении, или любые советы приветствуются.
Спасибо

2 ответа

Решение

Вы можете сделать это эффективно с динамическим программированием.

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

alphabet = 'abcd'
s = [ 'aabbbb', 'bacaaa', 'dabbbb', 'cabaaa']

# use memoized from http://wiki.python.org/moin/PythonDecoratorLibrary          
@memoized
def count(edits_left, index):
  if index == -1 and edits_left >= 0:
    return 1
  if edits_left < 0:
    return 0
  ret = 0
  for char in alphabet:
    edits_used = 0
    for mutate_str in s:
      if mutate_str[index] != char:
        edits_used += 1
    ret += count(edits_left - edits_used, index - 1)
  return ret

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

В общем случае для строки S длины L имеется в общей сложности C(L,K) (биномиальный коэффициент) позиций, которые можно заменить, и поэтому (ALPHABET_SIZE^K)*C(L,K) целевые строки T из Хэмминга Расстояние К.

Биномиальный коэффициент может быть довольно легко вычислен с помощью динамического программирования и треугольника Паскаля... Не нужно сходить с ума в множители и т. Д.

Теперь, когда рассматривается один строковый случай, работать с несколькими строками немного сложнее, поскольку вы можете удвоить количество целей. Интуитивно понятно, что если S1 находится K далеко от S2, то обе строки будут генерировать одинаковый набор целей, поэтому в этом случае вы не удваиваете счет. Это последнее утверждение может быть длинным выстрелом, поэтому я обязательно сказал "интуитивно":)

Надеюсь, поможет,

Другие вопросы по тегам