Изменения

Перейти к: навигация, поиск
м
rollbackEdits.php mass rollback
{{В разработкеОпределение|definition='''Палиндромом''' (англ. <i>Palindrome</i>) называется строка, которая одинаково читается как слева направо, так и справа налево.}}Задача о {{Определение|definition='''наибольшей подпоследовательностиПодпоследовательностью-палиндромапалиндромом данной строки''' — это задача поиска длины наибольшей подпоследовательности-палиндрома, которую можно получить вычеркиванием некоторых букв (англ. <i>Largest Palindromic Subsequence</i>) называется последовательность символов из данной последовательностистроки, не обязательно идущих подряд, являющаяся палиндромом. }}Например, '''''HELOLEH''''' является подпоследовательностью-палиндромом строки '''''HTEOLFEOLEH'''''.
{{Задача|definition == Определения ==Задача о '''наибольшей подпоследовательности-палиндроме''' {{---}} это задача о поиске наибольшей подпоследовательности, которую можно получить вычеркиванием некоторых букв из данной последовательности таким образом, что оставшаяся подпоследовательность будет палиндромом.}}
== Решение ==Обозначим данную последовательность через <tex>S</tex>, а ее элементы {{---}} через <tex>S[i], 0 \leqslant i \leqslant n - 1</tex>, где <tex>n</tex> {{Определение|definition='''Палиндромом''' называется строка---}} длина строки <tex>S</tex>. Будем рассматривать возможные подпоследовательности данной последовательности с <tex>i - </tex>го по <tex>j - </tex>ый символ включительно, которая одинаково читается обозначив её как слева направо<tex>S(i, так и справа налевоj)</tex>.Длины максимальных подпалиндромов для данной последовательности будем записывать в двумерный массив <tex>L</tex>: <tex>L[i][j]</tex> {{---}}длина максимальной подпоследовательности-палиндрома, который можно получить из последовательности <tex>S(i, j)</tex>.
Начнем решать задачу с простых подпоследовательностей. Для последовательности из одного элемента (то есть подпоследовательности вида <tex>S(i, i)</tex>) ответ очевиден {{Определение|definition='''Подпоследовательностью---}} ничего вычеркивать не надо, такая строка будет искомой подпоследовательностью-палиндромом данной строки''' называется последовательность символов . Для последовательности из данной строкидвух элементов <tex>S(i, i + 1)</tex> возможны два варианта: если элементы равны, то мы имеем подпоследовательность-палиндром, ничего вычеркивать не обязательно идущих подряднадо. Если же элементы не равны, являющаяся палиндромомто вычеркиваем любой. }}
'''''Например'''''Пусть теперь нам дана подпоследовательность <tex>S(i, '''''HELOLEH''''' является подпоследовательностью-палиндромом строки '''''HTEOLFEOLEH'''''j)</tex>. == Решение ==[[Файл:Palindrome11.png|200px|thumb|right|Массив длин подпоследовательностей-палиндромов]][[Файл:Palindrome12.png|200px|thumb|right|Наглядный массив переходов]]Обозначим данную последовательность через Если <tex>S[i]</tex>, а ее элементы — через и <tex>S[ij], 1 \le i \le n</tex> Будем рассматривать возможные элементы подпоследовательности данной последовательности с не совпадают, то один из них нужно вычеркнуть. Тогда у нас останется подпоследовательность <tex>S(i , j - 1)</tex>го по или <tex>S(i + 1, j-)</tex>ый символ, обозначим их как {{---}} то есть мы сведем задачу к подзадаче: <tex>SL[i][j] = \max(L[i][j - 1], L[i + 1][j])</tex>. Длины максимальных палиндромов для подпоследовательностей будем записывать в квадратный массив Если же первый и последний элементы равны, то мы можем оставить оба, но необходимо знать решение задачи <tex>S(i + 1, j - 1):L[i][j] = L[i + 1][j - 1] + 2</tex>. Таким образом получаем следующее рекуррентное соотношение:  <tex>L[i][j]</tex=\begin{cases} 1, & i = j\\ 0, & i > — длина максимальной подпоследовательностиj\\ L[i + 1][j -палиндрома1] + 2, который можно получить из подпоследовательности <tex>S& s[i] = s[j] \\ \max(L[i][j - 1], L[i + 1][j]), & s[i] \neq s[j]\end{cases}</tex>.
Начнем решать задачу с простых подпоследовательностей. Для последовательности из одного элемента (то есть подпоследовательности вида <tex>S(i, i)</tex>) ответ очевиден — ничего вычеркивать не надо, такая строка будет искомой подпоследовательностью-палиндромом. Для последовательности из двух элементов <tex>S(i, i + 1)</tex> возможны два варианта: если элементы равны, то мы имеем подпоследовательность-палиндром, ничего вычеркивать не надо. Если же элементы не равны, то вычеркиваем любой.
Пусть теперь нам дана подпоследовательность <tex>S(i, j)</tex>. Если первый <tex>(S[i])</tex> и последний <tex>(S[j])=== Асимптотика ===Каждый элемент массива мы вычисляем </tex> элементы подпоследовательности не совпадают, то один из них нужно вычеркнуть. Тогда у нас останется подпоследовательность <tex>S(i, j - 1)</tex> или раз за <tex>SO(i + 1, j)</tex> — то есть мы сведем задачу обращаясь к подзадаче: уже вычисленным элементам. Так как размер массива <tex>L[i][j] = max(L[i][j - 1], L[i + 1][j])n \times n</tex>. Если же первый и последний элементы равны, то мы можем оставить оба, но необходимо знать решение задачи алгоритм работает за <tex>SO(i + 1, j - 1n^2): L[i][j] = L[i + 1][j - 1] + 2</tex>.
== Пример ==
Рассмотрим решение на примере последовательности '''''ABACCBA'''''. Первым делом заполняем диагональ массива единицами, они будут соответствовать подпоследовательностями <tex>S(i, i)</tex> из одного элемента. Затем начинаем рассматривать подпоследовательности длины два. Во всех подпоследовательностях, кроме <tex>S(3, 4, 5)</tex>, элементы различны, поэтому в соответствующие ячейки запишем <tex>1</tex>, а в <tex>L[43][54]</tex> {{---}} <tex>2</tex>.
Получается, что мы будем заполнять массив по диагоналям, начиная с главной диагонали, ведущей из левого верхнего угла в правый нижний. Для подпоследовательностей длины <tex>3</tex> получаются следующие значения: в подпоследовательности '''''ABA''''' первый и последний элемент равны, поэтому <tex>L[10][32] = L[21][21] + 2</tex>. В остальных подпоследовательностях первый и последний элементы различны.
'''''BAC''''': <tex>L[2][4] = max(L[2][3], L[3][4]) = 1</tex>
'''''ACCBAC''''': <tex>L[31][53] = \max(L[31][42], L[42][53]) = 21</tex>
'''''CCBACC''''': <tex>L[42][64] = \max(L[42][53], L[53][64]) = 2</tex>
'''''CBACCB''''': <tex>L[53][75] = \max(L[53][64], L[64][75]) = 12</tex>
Продолжая далее аналогичные рассуждения, заполним все ячейки под диагональю и в ячейке '''''CBA''''': <tex>L[14][76]</tex> получим ответ <tex>= \max(L[4][5], L[5][6])= 1</tex>.
Продолжая далее аналогичные рассуждения, заполним все ячейки над диагональю и в ячейке <tex>L[0][6]</tex> получим ответ {{---}} <tex>6</tex>. Если же в задаче необходимо вывести не длину, а саму подпоследовательность-палиндром, то дополнительно к массиву длин мы должны построить массив переходов {{---}} для каждой ячейки запомнить, какой из случаев был реализован. Последовательность заполнения массива и массив переходов см. на изображениях ниже. [[Файл:Palindrome11.png|200px|Заполнение массива длин (1)]][[Файл:Palindrome12.png|200px|Заполнение массива длин (2)]][[Файл:Palindrome13.png|200px|Заполнение массива длин (3)]][[Файл:Palindrome14.png|200px|Заполнение массива длин (4)]][[Файл:Palindrome15.png|200px|Массив переходов]]
== Псевдокод ==
Перед вызовом процедуры заполняем <tex>L[][]</tex> начальными значениями: <tex>L[i][j] = 1</tex> если <tex>i=j</tex>, <tex>L[i][j] = 0</tex>, если <tex>i>j</tex>, в остальных случаях <tex>L[i][j]=-1</tex>.
При первом вызове функции в качестве аргументов передаем индексы первого и последнего элементов исходной строки. Например для строки длиной <tex> N </tex> вызов функции будет иметь следующий вид: <tex> \mathrm{palSubSeq(0, N - 1)}</tex>. Искомая же длина будет записана в ячейке <tex>L[0][N-1]</tex>.
Размещаем граничные случаи'''Функция для вычисления длины палиндрома''':*Границы исходной последовательности: <tex>F(I\mathtt{left, I) = 1right}</tex> и <texcode style = "display: inline-block;">F '''int''' palSubSeq(Ileft: '''int''', Jright: '''int''') : '''if''' L[left][right] = 0</tex>, если <tex>I > J</tex>. Теперь в рассматриваемой подстроке отделяем первый символ. Есть две возможности = -1 '''if''' s[left] == s[right] L[left][right] = palSubSeq(какая из них реализуетсяleft + 1, пока не знаем). Отделенный символ не участвует в образовании максимального подпоследовательностиright -палиндрома — тогда <tex>F(I, J1) + 2 '''else''' L[left][right] = Fmax(I palSubSeq(left + 1, Jright), palSubSeq(left, right - 1)) '''return''' L[left][right]</texcode>. Если же участвует, то ищем в подстроке с конца символ, совпадающий с отделенным (пусть его позиция '''Процедура для построения искомого палиндрома''':*Границы исходной последовательности: <tex>K\mathtt{left, right}</tex>)*Границы искомой подпоследовательности-палиндрома, тогда где правой границей будет длина найденного палиндрома: <tex>F(I\mathtt{palLeft, J) = 2 + F(I + 1, K – 1)palRight}</tex>. Надо предусмотреть еще случай <texcode style = "display: inline-block;">I <font color= K<green>//tex>palindrome {{---}} массив символов, а затем отсекать рекурсию.Получается следующая функция:где в palindrome[i] содержится символ искомой последовательности-палиндрома<code/font> Function FpalChars(ileft: '''int''', right: '''int''', palLeft: '''int''', jpalRight: '''int'''): '''while''' left <tex>\leqslant </tex> right '''if ''' left == right '''and''' L[i, jleft][right] == -1 k palindrome[palLeft++] = jS[left++] while '''else''' '''if''' S[ileft] <> == S[kright] k-- R1 palindrome[palLeft++] = F(i S[left++ 1, j)] if i <> k R2 palindrome[palRight--] = F(i + 1, k S[right-- 1) + 2] '''else''' R2 = 1 '''if R1 > R2 ''' L[i, jleft + 1][right] = R1 else <tex> > </tex> L[i, jleft] = R2 return L[i, jright - 1] left++ '''else''' right--
</code>
 
== Литература ==
* [[wikipedia:Palindrome|Wikipedia — Palindrome]]
* [[wikipedia:ru:Палиндром|Википедия — Палиндром]]
== См. также ==
* [[Задача о наибольшей общей подпоследовательности]]
* [[Задача о наибольшей возрастающей подпоследовательности]]
* [[Задача о наибольшей общей палиндромной подпоследовательности]]
 
==Источники информации==
* [[wikipedia:ru:Палиндром|Википедия {{---}} Палиндром]]
* [[wikipedia:Palindrome|Wikipedia {{---}} Palindrome]]
* [http://wcipeg.com/wiki/Longest_palindromic_subsequence Wikipedia {{---}} Longest palindromic subsequence]
[[Категория:Дискретная математика и алгоритмы]]
[[Категория:Динамическое программирование]]
1632
правки

Навигация