<?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.157.94&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.157.94&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.157.94"/>
		<updated>2026-08-03T11:09:33Z</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%BE%D0%B1%D1%89%D0%B5%D0%B9_%D0%B2%D0%BE%D0%B7%D1%80%D0%B0%D1%81%D1%82%D0%B0%D1%8E%D1%89%D0%B5%D0%B9_%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&amp;diff=33916</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%BE%D0%B1%D1%89%D0%B5%D0%B9_%D0%B2%D0%BE%D0%B7%D1%80%D0%B0%D1%81%D1%82%D0%B0%D1%8E%D1%89%D0%B5%D0%B9_%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&amp;diff=33916"/>
				<updated>2013-12-05T18:03:09Z</updated>
		
		<summary type="html">&lt;p&gt;217.66.157.94: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Даны два массива: &amp;lt;tex&amp;gt; a[1..n] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; b[1..m] &amp;lt;/tex&amp;gt;. Требуется найти их ''наибольшую общую возрастающую подпоследовательность (НОВП).''&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition = &lt;br /&gt;
'''Наибольшая общая возрастающая подпоследовательность (НОВП)''' (''англ''. longest common increasing subsequence - LCIS)  массива &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; и массива &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt; m &amp;lt;/tex&amp;gt; — это последовательность &amp;lt;tex&amp;gt; X = \left \langle x_1, x_2, ..., x_k \right \rangle &amp;lt;/tex&amp;gt; такая, что &amp;lt;tex&amp;gt; x_1 &amp;lt; x_2 &amp;lt; \dots &amp;lt; x_k &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; является ''подпоследовательностью'' &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
==Решение за время O(N&amp;lt;sup&amp;gt;4&amp;lt;/sup&amp;gt;)==&lt;br /&gt;
Построим следующую динамику: &amp;lt;tex&amp;gt; d[i][j] &amp;lt;/tex&amp;gt; - это длина наибольшей возрастающей подпоследовательности массивов &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; b &amp;lt;/tex&amp;gt;, последний элемент которой &amp;lt;tex&amp;gt; a[i] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; b[j] (a[i] = b[j]) &amp;lt;/tex&amp;gt;. Будем заполнять &amp;lt;tex&amp;gt; d[i][j] &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; d[i][j] &amp;lt;/tex&amp;gt; (где &amp;lt;tex&amp;gt; i = 1...n &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; j = 1...m. &amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Заполнять &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; будем следующим образом: на очередном шаге сравниваем элементы &amp;lt;tex&amp;gt; a[i] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; b[j] &amp;lt;/tex&amp;gt;:&lt;br /&gt;
*Если &amp;lt;tex&amp;gt; a[i] \neq b[j] &amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt; d[i][j] = 0 &amp;lt;/tex&amp;gt; (так как нет НОВП, оканчивающейся в разных элементах).&lt;br /&gt;
*Если &amp;lt;tex&amp;gt; a[i] = b[j] &amp;lt;/tex&amp;gt;, то эти элементы могут быть частью НОВП. Переберём, какие элементы стояли перед ними в массивах &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; b &amp;lt;/tex&amp;gt;. Заметим, что предыдущие значения &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; уже известны, тогда очередное значение &amp;lt;tex&amp;gt; d[i][j] = max(d[k][l] + 1, &amp;lt;/tex&amp;gt; для всех &amp;lt;tex&amp;gt; k = 1..i-1 &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; l = 1..j-1), &amp;lt;/tex&amp;gt; при условии, что &amp;lt;tex&amp;gt; a[k] = b[l] &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для восстановления подпоследовательности можно хранить массив предков &amp;lt;tex&amp;gt; prev[1..n] &amp;lt;/tex&amp;gt; массива &amp;lt;tex&amp;gt; a: prev[i] &amp;lt;/tex&amp;gt; - индекс предыдущего элемента НОВП, которая оканчивается в &amp;lt;tex&amp;gt; a[i] &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 vector&amp;lt;int&amp;gt; '''LCIS'''(vector&amp;lt;int&amp;gt; a, vector&amp;lt;int&amp;gt; b)&lt;br /&gt;
 d = int[n][m] // динамика&lt;br /&gt;
 prev = int[n] // массив предков&lt;br /&gt;
 '''for''' i = 1...n &lt;br /&gt;
    '''for''' j = 1...m&lt;br /&gt;
       '''if''' a[i] == b[j]&lt;br /&gt;
          d[i][j] = 1 // НОВП как минимум 1, состоит из одного элемента a[i] &amp;lt;-&amp;gt; b[j]&lt;br /&gt;
             '''for''' k = 1...i-1&lt;br /&gt;
                '''for''' l = 1...j-1&lt;br /&gt;
                   '''if''' a[k] == b[l] '''and''' a[k] &amp;lt; a[i] '''and''' d[i][j] &amp;lt; d[k][l] + 1&lt;br /&gt;
                      d[i][j] = d[k][l] + 1&lt;br /&gt;
                      prev[i] = k&lt;br /&gt;
 //  восстановление&lt;br /&gt;
 b_i = 1          // ищем лучшую пару (b_i, b_j)&lt;br /&gt;
 b_j = 1          // d[b_i][b_j] &amp;lt;tex&amp;gt; \rightarrow &amp;lt;/tex&amp;gt; max&lt;br /&gt;
 '''for''' i = 1...n&lt;br /&gt;
    '''for''' j = 1...m &lt;br /&gt;
       '''if''' d[b_i][b_j] &amp;lt; d[i][j]&lt;br /&gt;
          b_i = i&lt;br /&gt;
          b_j = j&lt;br /&gt;
 vector&amp;lt;int&amp;gt; answer&lt;br /&gt;
 pos = b_i        // проходим по массиву a, выписывая элементы НОВП&lt;br /&gt;
 '''while''' pos != 0&lt;br /&gt;
    answer.push(a[pos])&lt;br /&gt;
    pos = prev[pos]&lt;br /&gt;
 '''return''' answer&lt;br /&gt;
&lt;br /&gt;
==Решение за время O(N&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt;)==&lt;br /&gt;
Улучшим предыдущее решение. Пусть теперь &amp;lt;tex&amp;gt; d[i][j] &amp;lt;/tex&amp;gt; - динамика, в которой элемент &amp;lt;tex&amp;gt; a[i] &amp;lt;/tex&amp;gt; по-прежнему последний представитель НОВП массива &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt; b[j] &amp;lt;/tex&amp;gt; может не быть быть последним представителем массива &amp;lt;tex&amp;gt; b &amp;lt;/tex&amp;gt;. Тогда если &amp;lt;tex&amp;gt; a[i] \neq b[j] &amp;lt;/tex&amp;gt;, будем &amp;quot;протаскивать&amp;quot; последнее удачное сравнение в динамике: &amp;lt;tex&amp;gt; d[i][j] = d[i][j-1] &amp;lt;/tex&amp;gt; (понять это можно так: &amp;lt;tex&amp;gt; a[i] \neq b[j] &amp;lt;/tex&amp;gt; , поэтому &amp;lt;tex&amp;gt; b[j] &amp;lt;/tex&amp;gt; не последний представитель НОВП из массива &amp;lt;tex&amp;gt; b &amp;lt;/tex&amp;gt;, а значит предыдущий элемент НОВП находится в префиксе &amp;lt;tex&amp;gt; b[1..j-1] &amp;lt;/tex&amp;gt;, но &amp;lt;tex&amp;gt; d[i][j-1] &amp;lt;/tex&amp;gt; уже посчитан).&lt;br /&gt;
Если &amp;lt;tex&amp;gt; a[i] = b[j] &amp;lt;/tex&amp;gt;, то одним дополнительным циклом пробежим по &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt; и найдём предыдущий элемент НОВП, оканчивающейся в &amp;lt;tex&amp;gt; a[i] &amp;lt;/tex&amp;gt; (он меньше &amp;lt;tex&amp;gt; a[i] &amp;lt;/tex&amp;gt;). Из подходящих элементов выберем тот, для которого &amp;lt;tex&amp;gt; d[k][j] &amp;lt;/tex&amp;gt; - максимальна.&lt;br /&gt;
Правильнее было бы использовать индекс &amp;lt;tex&amp;gt; j-1 &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; d[k][j-1] &amp;lt;/tex&amp;gt;, то есть без элемента &amp;lt;tex&amp;gt; b[j] &amp;lt;/tex&amp;gt;. Но так как последовательность ''строго возрастает'', &amp;lt;tex&amp;gt; b[j] &amp;lt;/tex&amp;gt; точно не будет два раза элементом НОВП. Тогда мы, не рассматривая граничные случаи &amp;lt;tex&amp;gt; d[i][0] &amp;lt;/tex&amp;gt;, можем использовать индекс &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; в динамике &amp;lt;tex&amp;gt; d[k][j] &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; d[i][j] = max(d[k][j]) + 1 &amp;lt;/tex&amp;gt; для всех &amp;lt;tex&amp;gt; k = 1..i-1, a[k] &amp;lt; a[i]). &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 '''for''' i = 1...n &lt;br /&gt;
    '''for''' j = 1...m&lt;br /&gt;
       '''if''' a[i] == b[j]&lt;br /&gt;
          d[i][j] := 1 //НОВП как минимум 1, состоит из одного элемента a[i] &amp;lt;-&amp;gt; b[j]&lt;br /&gt;
          '''for''' k = 1...i-1&lt;br /&gt;
             '''if''' a[k] &amp;lt; a[i] '''and''' d[i][j] &amp;lt; d[k][j] + 1&lt;br /&gt;
                d[i][j] := d[k][j] + 1&lt;br /&gt;
                prev[i] := k&lt;br /&gt;
       '''else'''&lt;br /&gt;
          d[i][j] = d[i][j-1]&lt;br /&gt;
 //восстановление&lt;br /&gt;
 b_i := 1         //ищем лучший элемент d[b_i][m] &amp;lt;tex&amp;gt; \rightarrow &amp;lt;/tex&amp;gt; max&lt;br /&gt;
 '''for''' i = 1...n&lt;br /&gt;
    '''if''' d[b_i][m] &amp;lt; d[i][m]&lt;br /&gt;
       b_i := i&lt;br /&gt;
 print(d[b_i][m]) //размер НОВП&lt;br /&gt;
 pos := b_i       //проходим по массиву a, выписывая элементы НОВП&lt;br /&gt;
 '''while''' pos != 0&lt;br /&gt;
    print(a[pos])&lt;br /&gt;
    pos := prev[pos] &lt;br /&gt;
&lt;br /&gt;
==Решение за время O(N&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;)==&lt;br /&gt;
Пусть теперь &amp;lt;tex&amp;gt; d[i][j] &amp;lt;/tex&amp;gt; - это длина наибольшей общей возрастающей подпоследовательности префиксов &amp;lt;tex&amp;gt; a[1..i] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; b[1..j] &amp;lt;/tex&amp;gt; (элементы &amp;lt;tex&amp;gt; a[i] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; b[j] &amp;lt;/tex&amp;gt; могут не входить в НОВП). Вычислять &amp;lt;tex&amp;gt; d &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; a[i] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; b[j] &amp;lt;/tex&amp;gt; приходилось пробегать дополнительным циклом по массиву &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt; в поисках элемента, меньшего &amp;lt;tex&amp;gt; a[i] &amp;lt;/tex&amp;gt;, для которого &amp;lt;tex&amp;gt; d[k][j] &amp;lt;/tex&amp;gt; на префиксе &amp;lt;tex&amp;gt; a[1..k] &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; b[1..j] &amp;lt;/tex&amp;gt; была наилучшей. А раз мы считаем &amp;lt;tex&amp;gt; d &amp;lt;/tex&amp;gt; сначала по увеличению &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; , то &amp;lt;tex&amp;gt; a[i] &amp;lt;/tex&amp;gt; можно считать фиксированным, а &amp;lt;tex&amp;gt; b[j] &amp;lt;/tex&amp;gt; - переменным. Тогда давайте в дополнительной переменной хранить лучший элемент и его индекс в массиве &amp;lt;tex&amp;gt; b &amp;lt;/tex&amp;gt;, такой, что этот элемент строго меньше &amp;lt;tex&amp;gt; a[i] &amp;lt;/tex&amp;gt; и значение динамики для него максимально. Фактически, это решение отличается от предыдущих только более &amp;quot;хитрой&amp;quot; реализацией.&lt;br /&gt;
&lt;br /&gt;
 d[n][m]&lt;br /&gt;
 prev[m]&lt;br /&gt;
 '''for''' i = 1...n&lt;br /&gt;
    best_ind := 0 //позиция &amp;quot;лучшего&amp;quot; элемента в массиве b&lt;br /&gt;
    best := 0     //значение динамики для &amp;quot;лучшего&amp;quot; элемента&lt;br /&gt;
    '''for''' j = 1...m	&lt;br /&gt;
        d[i][j] := d[i-1][j]                           //НОВП на префиксе a[1..i-1] и b[1..j], то есть без элемента a[i]&lt;br /&gt;
        '''if''' a[i] == b[j] '''and''' d[i-1][j] &amp;lt; best + 1       //можем использовать a[i]-тый элемент для увеличения НОВП&lt;br /&gt;
            d[i][j] := best + 1                         &lt;br /&gt;
            p[j] := best_ind                            &lt;br /&gt;
        '''if''' a[i] &amp;gt; b[j] '''and''' d[i-1][j] &amp;gt; best  //в момент следующего равенства a[i] = b[j'] нам не придётся бежать циклом в поисках элемента k:&lt;br /&gt;
                best := d[i-1][j]              //b[k] &amp;lt; b[j'] = a[i]. Мы считаем элемент a[i] фиксированным и сравниваем кандидатов с ним&lt;br /&gt;
                best_ind := j&lt;br /&gt;
 //восстановление (по массиву b)&lt;br /&gt;
 b_j := 1 //ищем лучший элемент d[n][b_j]&amp;lt;tex&amp;gt; \rightarrow &amp;lt;/tex&amp;gt; max&lt;br /&gt;
 '''for''' k = 1...m&lt;br /&gt;
    '''if''' d[n][b_j] &amp;lt; d[n][j]&lt;br /&gt;
       b_j := j&lt;br /&gt;
 print(d[n][b_j]) //размер НОВП&lt;br /&gt;
 pos := b_j //проходим по массиву b, выписывая элементы НОВП&lt;br /&gt;
 '''while''' pos != 0&lt;br /&gt;
    print(b[pos])&lt;br /&gt;
    pos := prev[pos]&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
*[[Задача о наибольшей общей подпоследовательности]]&lt;br /&gt;
*[[Задача о наибольшей возрастающей подпоследовательности]]&lt;br /&gt;
&lt;br /&gt;
== Источники ==&lt;br /&gt;
&lt;br /&gt;
*http://codeforces.ru/contest/10/problem/D Codeforces - Задача о наибольшей общей возрастающей подпоследовательности&lt;br /&gt;
&lt;br /&gt;
[[Категория:Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория:Динамическое программирование]]&lt;/div&gt;</summary>
		<author><name>217.66.157.94</name></author>	</entry>

	</feed>