Задача о наименьшей суперпоследовательности — различия между версиями
| Motyaspr (обсуждение | вклад) | Motyaspr (обсуждение | вклад)  | ||
| Строка 1: | Строка 1: | ||
| {{Определение | {{Определение | ||
| |definition= | |definition= | ||
| − | Последовательность <tex> Z = \left \langle z_1, z_2, \dots, z_k \right \rangle </tex> является '''суперпоследовательностью''' (англ. ''supersequence'') последовательности <tex> X = \left \langle x_1, x_2, \dots,  | + | Последовательность <tex> Z = \left \langle z_1, z_2, \dots, z_k \right \rangle </tex> является '''суперпоследовательностью''' (англ. ''supersequence'') последовательности <tex> X = \left \langle x_1, x_2, \dots, x_n \right \rangle </tex>, если существует ''строго возрастающая'' последовательность <tex> \left \langle i_1, i_2, \dots, i_m \right \rangle </tex> индексов <tex> Z </tex> таких, что для всех <tex> j = 1, 2, \dots, m </tex> выполняется соотношение <tex> z_{i_j} = x_j </tex>. | 
| }} | }} | ||
Версия 23:01, 23 декабря 2017
| Определение: | 
| Последовательность является суперпоследовательностью (англ. supersequence) последовательности , если существует строго возрастающая последовательность индексов таких, что для всех выполняется соотношение . | 
| Определение: | 
| Последовательность является общей суперпоследовательностью (англ. common supersequence) последовательностей и , если является суперпоследовательностью как для , так для и . | 
| Задача: | 
| Пусть имеются последовательности и . Необходимо найти | 
Содержание
Наивное решение
Пусть даны две последовательности длины и соответственно. Заметим, что если приписать к одной из данных последовательностей другую, то полученная последовательность будет их суперпоследовательностью с длиной . Запомним все элементы обеих последовательностей и из них построим все возможные последовательности. Тогда искомая гарантированно найдётся, однако время работы алгоритма будет экспоненциально зависеть от длины исходных последовательностей.
Динамическое программирование
Решение
Обозначим за префиксов данных последовательностей и , заканчивающихся в элементах с номерами и соответственно. Наименьшая общая суперпоследовательность и должна содержать каждый символ обеих последовательностей, поэтому если , то это просто последовательность . Аналогичен случай, когда . Если и , то возможны два случая. Если , то SCS должна включать оба этих элемента. Значит нужно выбрать минимальный из ответов для префиксов, включающих один элемент и не включающих второй. Если же , то для последовательностей и должна заканчиваться этим элементом, так как он общий для них. Получается следующее рекуррентное соотношение:
Cложность алгоритма составит , где и — длины последовательностей.
Восстановление ответа
Для восстановления ответа заведем массив , где будет означать индексы в массиве , при которых достигалось наименьшее значение .
Псевдокод
x, y — данные последовательности; — SCS для префикса длины i последовательности x и префикса длины j последовательности y; prev[i][j] — пара индексов элемента таблицы, которые предшествовали .
fun SCS(x: int, y: int):    // аналог void 
   n = x.size
   m = y.size
   for i = 1 to n
     scs[i][0] = i
   for j = 0 to m
     scs[0][j] = j
   for i = 1 to n
     for j = 1 to m
       if x[i] == y[j]
         scs[i][j] = 1 + scs[i - 1][j - 1]
         prev[i][j] = pair(i - 1, j - 1)
       else
         if scs[i - 1][j] <= lcs[i][j - 1]
           scs[i][j] = 1 + scs[i - 1][j]
           prev[i][j] = pair(i - 1, j)
         else
           scs[i][j] = 1 + scs[i][j - 1]
           prev[i][j] = pair(i, j - 1)
 
fun printLCS(n: int, m: int): // вывод SCS
   i = n
   j = m
   ans = [] // массив ответа 
   while i > 0 and j > 0
     if prev[i][j] == pair(i - 1, j - 1)
       ans.append(x[i])
       i -= 1
       j -= 1
     else
       if prev[i][j] == pair(i - 1, j)
         ans.append(x[i])
         i -= 1
       else
         ans.append(y[j])
         j -= 1
   while i > 0 // добавляем оставшиеся символы первой последовательности 
     ans.append(x[i])
     i -= 1
   while j > 0
     ans.append(y[j]) // добавляем оставшиеся символы второй последовательности 
     j -= 1
   reverse(ans) // разворачиваем последовательность, так как шли с конца 
   return ans
Связь с наибольшей общей подпоследовательностью
| Теорема: | 
| , где  - длина  наибольшей общей подпоследовательности,  - длина наименьшей общей суперпоследовательности,  и  - длины последовательностей  и  соответсвенно. | 
| Доказательство: | 
| Пусть , . Обозначим за их SCS и будем ее строить. Так как являетcя суперпоследовательностью , то можно представить так: Мы должны поставить на место некоторых пропусков поставить элементы , так чтобы суммарная длина была минимальна, и был суперпоследовательностью . Рассмотрим любую общую подпоследовательность и .Заметим, что она уже находятся в , а значит все её элементы не нужно добавлять. Поэтому мы добавим не меньше чем . Длину нужно минимизировать, значит имеет место равенство: .Поэтому: | 
