Re: Неубывающая подпоследовательность

From
Viktor Karev ()
To
All ()
Date
2000-02-22T21:20:08Z
Area
RU.ALGORITHMS
From: "Viktor Karev" <karev@post.krascience.rssi.ru>

Приветствия, Dmitry Buzin!

>     Требуется найти самую длинную неубывающую подпоследовательность в
> последовательности целых чисел, избежав при этом полного перебора.
>     Задача, в принципе, не очень сложная, но ничего, кроме модификации
метода
> бинарного поиска в голову не приходит. ;)

Эта задача очень хорошо описана у Д.Гриса в книге "Наука программирования".
Основная идея: если есть последовательность b[0:i-1]. Ясно, что для каждого
k есть минимальное значение m, завершающее в этой последовательности
восходящую подпоследовательность длины k.
Теперь добавим еще один член последовательности, b[i].
Если b[i]>=m, то просто увеличиваем k, и новое m равно b[i].
Если же b[i]<m, то выясняется, что нам нужен массив m[], в котором мы
запоминаем значения m для каждого k.

Введем обозначение lup(s) - длина самой длинной восходящей
последовательности из s.
Таким образом, программа имеет пред- и постусловие
Q: n>0
R: k=lup(b[0:n-1])

.... Анализ пропущен.

Вводится инвариант цикла
P: ((0<=i<=n) and (k=lup(b[0:n-1])) and
    (для любого j: 1<=j<=k, справедливо, что m[j] является наименьшим
значением, завершающим восходящую последовательность длины k в b[0:i-1])

i:=1; k:=1; m[1]:=b[0]; {P}
пока i<>n цикл
  если b[i]<=m[k]      то k:=k+1; m[k]:=b[i];
       b[i]<m[1]       то m[1]:=b[i];
       m[1]<=b[i]<m[k] то
           ** Установить m[j-1]<=b[i]<m[j]:
           h:=1; j:=k;
           {Инвариант: (1<=h<j<=k) and (m[h]<=b[i]<m[j])}
           пока h<>j-1 цикл
             e:=(h+j)%2;
             если m[e]<=b[i] то h:=e
                  m[e]>b[i]  то j:=e
             конец если
           конец цикла
           m[j]:=b[i]
  конец если
  i:=i+1
конец цикла

Виктор
--- ifmail v.2.15dev4
 * Origin: Персональный компьютер (2:5020/400)