<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=217.66.159.22&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=217.66.159.22&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/217.66.159.22"/>
		<updated>2026-08-04T13:35:37Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%BD%D0%B0%D0%B8%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%B5%D0%B9_%D0%BF%D0%BE%D0%B4%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8-%D0%BF%D0%B0%D0%BB%D0%B8%D0%BD%D0%B4%D1%80%D0%BE%D0%BC%D0%B5&amp;diff=42010</id>
		<title>Задача о наибольшей подпоследовательности-палиндроме</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D0%BD%D0%B0%D0%B8%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%B5%D0%B9_%D0%BF%D0%BE%D0%B4%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8-%D0%BF%D0%B0%D0%BB%D0%B8%D0%BD%D0%B4%D1%80%D0%BE%D0%BC%D0%B5&amp;diff=42010"/>
				<updated>2014-12-09T11:26:17Z</updated>
		
		<summary type="html">&lt;p&gt;217.66.159.22: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Задача о '''наибольшей подпоследовательности-палиндрома''' — это задача поиска длины наибольшей подпоследовательности-палиндрома, которую можно получить вычеркиванием некоторых букв из данной последовательности.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Определения ==&lt;br /&gt;
{{Определение|definition='''Палиндромом''' называется строка, которая одинаково читается как слева направо, так и справа налево.}}&lt;br /&gt;
{{Определение|definition='''Подпоследовательностью-палиндромом данной строки''' называется последовательность символов из данной строки, не обязательно идущих подряд, являющаяся палиндромом. }}&lt;br /&gt;
'''''Например''''', '''''HELOLEH''''' является подпоследовательностью-палиндромом строки '''''HTEOLFEOLEH'''''. &lt;br /&gt;
== Решение ==&lt;br /&gt;
Обозначим данную последовательность через &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, а ее элементы — через &amp;lt;tex&amp;gt;S[i], 0 \le i \le n - 1&amp;lt;/tex&amp;gt;. Будем рассматривать возможные подпоследовательности данной последовательности с &amp;lt;tex&amp;gt;i - &amp;lt;/tex&amp;gt;го по &amp;lt;tex&amp;gt;j-&amp;lt;/tex&amp;gt;ый символ включительно, обозначив её как &amp;lt;tex&amp;gt;S(i, j)&amp;lt;/tex&amp;gt;. Длины максимальных подпалиндромов для данной последовательности будем записывать в квадратный массив &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;L[i][j]&amp;lt;/tex&amp;gt; — длина максимальной подпоследовательности-палиндрома, который можно получить из последовательности &amp;lt;tex&amp;gt;S(i, j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Начнем решать задачу с простых подпоследовательностей. Для последовательности из одного элемента (то есть подпоследовательности вида &amp;lt;tex&amp;gt;S(i, i)&amp;lt;/tex&amp;gt;) ответ очевиден — ничего вычеркивать не надо, такая строка будет искомой подпоследовательностью-палиндромом. Для последовательности из двух элементов &amp;lt;tex&amp;gt;S(i, i + 1)&amp;lt;/tex&amp;gt; возможны два варианта: если элементы равны, то мы имеем подпоследовательность-палиндром, ничего вычеркивать не надо. Если же элементы не равны, то вычеркиваем любой.&lt;br /&gt;
&lt;br /&gt;
Пусть теперь нам дана подпоследовательность &amp;lt;tex&amp;gt;S(i, j)&amp;lt;/tex&amp;gt;. Если &amp;lt;tex&amp;gt;S[i]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S[j]&amp;lt;/tex&amp;gt; элементы подпоследовательности не совпадают, то один из них нужно вычеркнуть. Тогда у нас останется подпоследовательность &amp;lt;tex&amp;gt;S(i, j - 1)&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;S(i + 1, j)&amp;lt;/tex&amp;gt; — то есть мы сведем задачу к подзадаче: &amp;lt;tex&amp;gt;L[i][j] = max(L[i][j - 1], L[i + 1][j])&amp;lt;/tex&amp;gt;. Если же первый и последний элементы равны, то мы можем оставить оба, но необходимо знать решение задачи &amp;lt;tex&amp;gt;S(i + 1, j - 1): &lt;br /&gt;
L[i][j] = L[i + 1][j - 1] + 2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
=== Асимптотика ===&lt;br /&gt;
Каждый элемент массива мы вычисляем 1 раз за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; обращаясь к уже вычисленным элементам. Так как размер массива &amp;lt;tex&amp;gt;n \times n&amp;lt;/tex&amp;gt;, то алгоритм работает за &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Пример ==&lt;br /&gt;
Рассмотрим решение на примере последовательности '''''ABACCBA'''''. Первым делом заполняем диагональ массива единицами, они будут соответствовать подпоследовательностями &amp;lt;tex&amp;gt;S(i, i)&amp;lt;/tex&amp;gt; из одного элемента. Затем начинаем рассматривать подпоследовательности длины два. Во всех подпоследовательностях, кроме &amp;lt;tex&amp;gt;S(3, 4)&amp;lt;/tex&amp;gt;, элементы различны, поэтому в соответствующие ячейки запишем &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а в &amp;lt;tex&amp;gt;L[3][4]&amp;lt;/tex&amp;gt; — &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получается, что мы будем заполнять массив по диагоналям, начиная с главной диагонали. Для подпоследовательностей длины &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; получаются следующие значения: в подпоследовательности '''''ABA''''' первый и последний элемент равны, поэтому &amp;lt;tex&amp;gt;L[0][2] = L[1][1] + 2&amp;lt;/tex&amp;gt;. В остальных подпоследовательностях первый и последний элементы различны.&lt;br /&gt;
&lt;br /&gt;
'''''BAC''''': &amp;lt;tex&amp;gt;L[1][3] = max(L[1][2], L[2][3]) = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''''ACC''''': &amp;lt;tex&amp;gt;L[2][4] = max(L[2][3], L[3][4]) = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''''CCB''''': &amp;lt;tex&amp;gt;L[3][5] = max(L[3][4], L[4][5]) = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''''CBA''''': &amp;lt;tex&amp;gt;L[4][6] = max(L[4][5], L[5][6]) = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Продолжая далее аналогичные рассуждения, заполним все ячейки над диагональю и в ячейке &amp;lt;tex&amp;gt;L[0][6]&amp;lt;/tex&amp;gt; получим ответ {{---}} &amp;lt;tex&amp;gt;6&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Если же в задаче необходимо вывести не длину, а саму подпоследовательность-палиндром, то дополнительно к массиву длин мы должны построить массив переходов — для каждой ячейки запомнить, какой из случаев был реализован.&lt;br /&gt;
&lt;br /&gt;
Последовательность заполнения массива и массив переходов см. на изображениях ниже.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Palindrome11.png|200px|Заполнение массива длин (1)]]&lt;br /&gt;
[[Файл:Palindrome12.png|200px|Заполнение массива длин (2)]]&lt;br /&gt;
[[Файл:Palindrome13.png|200px|Заполнение массива длин (3)]]&lt;br /&gt;
[[Файл:Palindrome14.png|200px|Заполнение массива длин (4)]]&lt;br /&gt;
[[Файл:Palindrome15.png|200px|Массив переходов]]&lt;br /&gt;
&lt;br /&gt;
== Псевдокод ==&lt;br /&gt;
Перед вызовом процедуры заполняем &amp;lt;tex&amp;gt;L[][]&amp;lt;/tex&amp;gt; начальными значениями: &amp;lt;tex&amp;gt;L[i][j] = 1&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i=j&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;L[i][j] = 0&amp;lt;/tex&amp;gt;, если &amp;lt;tex&amp;gt;i&amp;gt;j&amp;lt;/tex&amp;gt;, в остальных случаях &amp;lt;tex&amp;gt;L[i][j]=-1&amp;lt;/tex&amp;gt;. &lt;br /&gt;
При первом вызове функции в качестве аргументов передаем индексы первого и последнего элементов исходной строки. Например для строки длиной &amp;lt;tex&amp;gt; N &amp;lt;/tex&amp;gt; вызов функции будет иметь следующий вид: &amp;lt;tex&amp;gt;palSubSeq(0,N - 1)&amp;lt;/tex&amp;gt;. Искомая же длина будет записана в ячейке &amp;lt;tex&amp;gt;L[0][N-1]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Функция для вычисления длины палиндрома''' (&amp;lt;tex&amp;gt;left, right&amp;lt;/tex&amp;gt; - границы исходной последовательности):&lt;br /&gt;
&amp;lt;code style = &amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
  '''palSubSeq'''(left, right):&lt;br /&gt;
    '''if''' L[left][right] == -1 &lt;br /&gt;
        '''if''' s[left] == s[right] &lt;br /&gt;
            L[left][right] = palSubSeq(left + 1, right - 1) + 2&lt;br /&gt;
         '''else''' &lt;br /&gt;
            L[left][right] = max(palSubSeq(left + 1, right), palSubSeq(left, right - 1))&lt;br /&gt;
    '''return''' L[left][right]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
'''Функция для построения искомого палиндрома''' (&amp;lt;tex&amp;gt;left, right&amp;lt;/tex&amp;gt; {{---}} границы исходной последовательности, &amp;lt;tex&amp;gt;palLeft=0, palRight=L[0][n-1]-1&amp;lt;/tex&amp;gt; {{---}} границы искомой):&lt;br /&gt;
&amp;lt;code style = &amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
  // palindrome {{---}} массив символов, где в palindrome[i] содержится символ искомой последовательности-палиндрома&lt;br /&gt;
  '''palChars'''(left, right, palLeft, palRight)&lt;br /&gt;
    '''while''' left &amp;lt;tex&amp;gt;\leqslant&amp;lt;/tex&amp;gt; right&lt;br /&gt;
      '''if''' left == right '''and''' L[left][right] == 1&lt;br /&gt;
        palindrome[palLeft++] = S[left++]&lt;br /&gt;
      '''else'''&lt;br /&gt;
        '''if''' S[left] == S[right]&lt;br /&gt;
          palindrome[palLeft++] = S[left++]&lt;br /&gt;
          palindrome[palRight--] = S[right--]&lt;br /&gt;
        '''else'''&lt;br /&gt;
          '''if''' L[left + 1][right] &amp;lt;tex&amp;gt; &amp;gt; &amp;lt;/tex&amp;gt; L[left][right - 1]&lt;br /&gt;
            left++&lt;br /&gt;
          '''else'''&lt;br /&gt;
            right--&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
* [[wikipedia:Palindrome|Wikipedia — Palindrome]]&lt;br /&gt;
* [[wikipedia:ru:Палиндром|Википедия — Палиндром]]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Задача о наибольшей общей подпоследовательности]]&lt;br /&gt;
* [[Задача о наибольшей возрастающей подпоследовательности]]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория:Динамическое программирование]]&lt;/div&gt;</summary>
		<author><name>217.66.159.22</name></author>	</entry>

	</feed>