Informatyczny kącik olimpijski
Neon
O pewnym zadaniu z zeszłorocznego Obozu Naukowo-Treningowego im. A. Kreczmara.
Na przykład dla neonu supermarket stokrotka możemy uzyskać 17 różnych niepustych podciągów (skt, sra, srk, srt i ich krótsze podciągi) na 27 sposobów (np. srk możemy uzyskać na 2 sposoby). Wynik należy obliczyć modulo pewna liczba całkowita.
Zadanie rozwiążemy, używając metody programowania dynamicznego. Niech i będą słowami neonu. Będziemy wypełniać prostokątną tablicę Dla oznaczmy przez liczbę sposobów, na jakie możemy zgasić litery w słowach oraz tak by pozostałe litery tworzyły ten sam (być może pusty) podciąg. Odpowiedzią do pierwszej części zadania jest, oczywiście,
Jeśli lub (tzn. gdy jedno ze słów jest puste), to możemy utworzyć tylko pusty podciąg, zatem
Załóżmy zatem, że i spójrzmy na ostatnie litery słów i Załóżmy na początek, że są one równe, tzn. Rozważmy cztery przypadki w zależności od tego, czy zostawiamy te litery zapalone, czy też nie. Jeśli obie będą zapalone, to znaczy, że uzyskane podciągi powstają z rozszerzenia jednego z podciągów dla słów i o dodatkową literę. To daje możliwości. Liczba możliwych podciągów w przypadku, gdy litera zostanie zgaszona, wynosi Analogicznie liczba podciągów, gdy litera zostanie zgaszona, wynosi Zauważmy, że te podciągi, które wystąpią w przypadku zgaszenia obu tych liter, uwzględniliśmy już w wyniku, z tym że policzyliśmy je dwukrotnie, należy zatem odjąć ich liczbę (jest ich ). Ostatecznie dostajemy prostą zależność
Przypadek jest trochę łatwiejszy: nie możemy naraz zapalić liter i zatem Zajmiemy się teraz drugą częścią zadania: obliczeniem liczby różnych wspólnych podciągów. Na pierwszy rzut oka może się wydawać, że w tym przypadku będziemy musieli zastosować zupełnie inną strategię i potrzebna będzie jakaś struktura danych, która umożliwi nam wyłapywanie duplikatów. Okazuje się jednak, że i ten problem można rozwiązać za pomocą zaskakująco prostej zależności rekurencyjnej.
Niech oznacza liczbę różnych wspólnych podciągów, które możemy utworzyć w słowach Dla lub mamy, oczywiście, Znów patrzymy na ostatnie litery słów. Niech Okazuje się, że w tym przypadku mamy po prostu a rozumowanie jest analogiczne jak dla tablicy
Niech teraz Każdy wspólny podciąg słów i należy do co najmniej jednego z dwóch zbiorów: zbioru tych różnych podciągów, które mogą powstać, gdy obie litery są zapalone, oraz zbioru tych różnych podciągów, które mogą powstać, gdy obie te litery są zgaszone. Zatem Zbiory i mają po elementów, pozostaje zatem obliczyć liczność ich części wspólnej Niech oznacza największą liczbę dodatnią mniejszą niż dla której ; analogicznie niech będzie największą liczbą dla której Jeśli choć jedna z tych liczb nie istnieje, to W przeciwnym przypadku mamy i wówczas
Pozostaje oszacować złożoność naszego algorytmu. Tablice i możemy obliczyć w czasie i takiej pamięci. Czas wypełniania tablic i to bezpośrednia realizacja da też taką złożoność pamięciową. Zauważmy jednak, że w przypadku tablicy możemy zastosować standardową sztuczkę: jeśli wypełniamy tablicę wierszami, wystarczy trzymać w pamięci jedynie aktualny ( -ty) i ostatnio wypełniony ( -szy) wiersz – nigdy bowiem nie odwołujemy się do komórek z wierszy o numerach mniejszych niż Problem powstaje w przypadku tablicy w której korzystamy z wiersza o numerze Tu jednak radzimy sobie następująco: oprócz ostatnich dwóch wierszy trzymamy dodatkowo tablicę W przypadku, gdy uaktualniamy ją według wzoru Dzięki temu mamy Ostatecznie złożoność pamięciowa algorytmu wyniesie