• Nie Znaleziono Wyników

PODCIĄGI ROSNĄCE

2. Najdłuższy podciąg rosnący

2.1. Wprowadzenie

Problem wyznaczania najdłuższego podciągu rosnącego (ang. longest increasing subsequ-ence, LIS) w ciągu liczbowym zajmował uwagę matematyków i informatyków od początku XX w. Początkowo rozważano go w kategoriach czysto teoretycznych, ale w ostatnich latach znalazł zastosowanie w wielu dziedzinach, o czym będzie mowa w dalszej części niniejszego rozdziału. Problem ten można zdefiniować następująco:

Problem 2.1 (Najdłuższy podciąg rosnący, LIS). Dla skończonego ciągu liczbowego A = a1a2

. . . annależy znaleźć podciąg ai1ai2. . . ai` o maksymalnej długości, taki że 1≤ i1< i2< ··· <

i`≤ n oraz ai1 < ai2< ··· < ai`.

Przykład 2.1 (Najdłuższy podciąg rosnący, LIS). Dla ciągu liczbowego A = 4 6 2 8 1 3 12 9 5 7 11 10 najdłuższym podciągiem rosnącym jest m.in. A0= 2 3 5 7 10. W ciągu A podkreślono symbole tworzące podciąg LIS.

Zgodnie z powyższą definicją, szukany podciąg musi być ściśle rosnący. Istnieje także od-miana tego problemu, w którym wymagane jest tylko, aby otrzymany podciąg był niemalejący.

Definicja tego problemu podana jest poniżej.

Problem 2.2 (Najdłuższy podciąg niemalejący). Dla skończonego ciągu liczbowego A = a1a2

. . . annależy znaleźć podciąg ai1ai2. . . ai` o maksymalnej długości, taki że 1≤ i1< i2< ··· <

i`≤ n oraz ai1 ≤ ai2≤ ··· ≤ ai`.

Przykład 2.2 (Najdłuższy podciąg niemalejący). Dla ciągu liczbowego A = 4 6 2 8 1 3 3 12 9 9 5 7 11 10 najdłuższym podciągiem rosnącym jest m.in. A0= 2 3 3 5 7 10. W ciągu A podkre-ślono symbole tworzące podciąg LIS.

Jeśli symbole ciągu są unikalne, to oczywiście obie powyższe definicje są równoważne.

Ponadto, pomiędzy obiema wersjami tego problemu zachodzi ścisły związek, tj. dysponując algorytmem rozwiązywania ściśle rosnącego wariantu problemu LIS, można rozwiązać drugi wariant przekształcając ciąg wejściowy w następujący sposób:

1. Posortuj stabilnym algorytmem sortowania elementy ciągu wejściowego.

2. Zastąp każdy element ciągu wejściowego jego indeksem w ciągu posortowanym.

Powyższe przekształcenie powoduje, że identyczne elementy ciągu wejściowego zostaną za-stąpione przez kolejne liczby całkowite. W bardzo podobny sposób można przekształcić ciąg

wejściowy, aby do wyznaczenia ściśle rosnącego podciągu LIS móc zastosować algorytm dla wariantu nieściśle rosnącego. Złożoność czasowa przekształcenia ciągu wejściowego zależy od użytego algorytmu sortowania i zwykle jest O(n logn). W dalszej części niniejszej pracy roz-ważana będzie tylko wersja ściśle rosnąca problemu LIS.

2.2. Dodatkowe definicje i przyjęte założenia

W rozdziałach 2–6 będzie przyjmowane, że ciągiem wejściowym jest A = a1a2. . . an. Ele-menty (symbole) tego ciągu należą do alfabetuΣ, który jest podzbiorem zbioru liczb całkowi-tych. W niektórych sytuacjach dogodne jest przyjęcie dodatkowego założenia, że alfabet jest ograniczony, tj.Σ= {0,...,σ− 1}. W tej sytuacji σjest rozmiarem alfabetu. Przez rangę ele-mentu ai, oznaczaną przez h(ai), będzie rozumiana długość najdłuższego rosnącego podciągu kończącego się na ai. Długość ciągu wynikowego dla każdego problemu rozpatrywanego w ni-niejszej części będzie oznaczana przez `.

2.3. Długość najdłuższego podciągu rosnącego

Pierwsze oszacowania długości podciągu LIS można znaleźć w pracy Erdösa i Szekere-sa [83] z 1935 roku, którzy rozważali pewien problem geometryczny, a jednym z wyników pośrednich było wykazanie, że w dowolnym ciągu liczbowym występuje rosnący bądź maleją-cy podciąg o długości co najmniej√

n(patrz również [193]), z czego natychmiast wynika, że oczekiwana długość podciągu LIS w ciągu będącym losową permutacją zbioru n liczb całkowi-tych to co najmniej 12

n− 1. Późniejsze symulacje numeryczne [24] z 1968 roku wskazywały, że wartość oczekiwana tej długości jest bliska 2√n. W 1972 roku Hammersley [107] wykazał, że istnieje pewna stała c taka, że oczekiwana długość podciągu LIS to c

n+ o(

n), a Vershik i Kerov [211] wykazali, że c = 2. Pełny rozkład prawdopodobieństwa wartości oczekiwanej długości podciągu LIS wyznaczyli Baik i in. [27] w 1999 roku. Wyniki, które uzyskali, mówią m.in., że wartość oczekiwana tej długości to 2n1/2−Θ(n1/6), podczas gdy odchylenie standar-dowe jestΘ(n1/6). Ciekawym artykułem przeglądowym, który podsumowuje osiągnięcia w tej dziedzinie, jest [5].

2.4. Algorytmy

2.4.1. Tableau Younga

Istnieje wiele algorytmów wyznaczania podciągu LIS. Historycznie pierwszy taki algorytm został przedstawiony przez Schensteda [188]. Idea jego działania opiera się na konstrukcji

ta-2.4. Algorytmy 37 Tableau-Insert(T , x)

Wejście: T – tableau postaci (n1, n2, . . . , nN) x– liczba wstawiana do T

Wyjście: tableau po wstawieniu do niego x 1 for i ← 1 to N do

2 y← najmniejsza liczba większa od x znajdująca się w wierszu i 3 if y istnieje then

4 Zamień y w wierszu i z x

5 else

6 Wstaw x na końcu wiersza i

7 return T

8 Rozszerz tableau T przez wstawienie wiersza zawierającego x 9 return T

Rys. 2.1. Algorytm wstawiania liczby do tableau Younga Fig. 2.1. Algorithm inserting an integer to Young tableau

bleau Younga [222], która to struktura zostanie poniżej przybliżona. Tableau Younga zostało zaproponowane jako metoda badania macierzowych reprezentacji permutacji. Jest ono pew-nym sposobem rozmieszczenia n liczb całkowitych w tabeli składającej się z wierszy różnej długości.

Definicja 2.1. Tableau Younga postaci (n1, n2, . . . , nN) jest metodą reprezentacji n1+ n2+

··· + nN = n liczb całkowitych, przy czym n1 ≥ n2 ≥ ··· ≥ nN. Składa się ono z N wierszy o długościach n1, n2, . . . , nN. Elementy w każdym wierszu uporządkowane są rosnąco od le-wej do prale-wej strony. Każda kolumna zawiera elementy uporządkowane rosnąco od góry do dołu.

Tableau dla ciągu tworzy się rozpoczynając od pustej struktury, do której wstawia się ko-lejne elementy za pomocą algorytmu Tableau-Insert (rys. 2.1). Algorytm ten wyszukuje w pierwszym wierszu najmniejszą liczbę większą niż liczba wstawiana i zamienia te liczby ze sobą. Następnie wykonuje to samo w kolejnych wierszach. Jeśli w którymkolwiek kroku liczba większa niż bieżąca nie istnieje, to algorytm wstawia bieżącą liczbę na koniec bieżącego wiersza i kończy swoje działanie. Przykład działania tego algorytmu został przedstawiony na rys. 2.2. Jak wykazał Schensted [188], długość pierwszego wiersza, n1, jest jednocześnie dłu-gością podciągu LIS, a z samej tej struktury można w odpowiedni sposób odczytać podciąg LIS. Czytelnik zainteresowany szczegółami działania tego algorytmu może znaleźć dokładny opis w [5, 188]. Złożoność czasowa algorytmu wyznaczania podciągu LIS za pomocą tableau Younga jest O(n logn).

Więcej informacji na temat samego tableau Younga i jego właściwości oraz opis innych operacji na nim, nieistotnych dla niniejszej pracy, można znaleźć m.in. w [94, 130, 95, 171].

4 4 6 2

Rys. 2.2. Ilustracja działania algorytmu tworzenia tableau Younga dla A = 4 6 2 8 1 3 12 9 5 7 11 10.

Aktualnie wstawiane elementy są zaznaczone na szaro

Fig. 2.2. Example of the algorithm building Young tableau for A = 4 6 2 8 1 3 12 9 5 7 11 10. The just placed elements are in gray

2.4.2. Pokrycie zachłanne

Gusfield w książce [106] przedstawia algorytm wyznaczania podciągu LIS oparty na idei reprezentacji ciągu w postaci pokrycia zachłannego (ang. greedy cover). Koncepcja pokrycia ciągu jest podstawą rozważań prowadzonych w kilku kolejnych rozdziałach.

Definicja 2.2. Pokryciem ciągu A jest uporządkowany zbiór list, z których każda zawiera ma-lejący podciąg ciągu A. Każdy element ciągu A należy do dokładnie jednej z list.