Informatyczny kącik olimpijski
Palindromiczny podciąg
W tym miesiącu omówimy zadanie Palindromic Subsequence, które pojawiło się na konkursie SRM 708 na platformie Topcoder.
Palindrom to słowo, które nie zmienia się, gdy czytamy je od prawej do lewej, np. "kajak" lub "abba".
W zadaniu dane jest słowo o długości
znaków. Dla każdego indeksu
mamy znaleźć liczbę palindromicznych podciągów
które zawierają
-tą literę
Wyniki należy wypisać modulo
Innymi słowy: dla ustalonego mamy
sposobów na usunięcie niektórych z pozostałych
liter w
Interesuje nas liczba sposobów, dla których nieusunięte litery utworzą palindrom (
-ta litera jest, oczywiście, nieusunięta).
Zacznijmy od rozwiązania prostszego zadania - policzmy wszystkie palidromiczne podciągi w danym słowie.
Złym pomysłem jest przetwarzanie słowa od lewej do prawej, bo zapewne musielibyśmy dokładnie pamiętać już wybrany podciąg, by później wybrać te same litery w odwróconej kolejności (by powstał palindrom). Zamiast tego policzymy wynik dla każdego przedziału, zaczynając od przedziałów o długości
Niech oznacza liczbę palindromicznych podciągów przedziału
(tzn. palindromicznych podciągów podsłowa złożonego z liter
). Szczegółem implementacyjnym jest decyzja, czy należy liczyć puste podciągi. Zacznijmy analizę od wstępnego wzoru (wcale nieprzypadkowo podobnego do wzoru na liczenie sum prefiksowych w macierzy!):
![in[i][ j] = in[i +1][ j]+ in[i][ j − 1] −in[i +1][ j− 1].](/math/temat/informatyka/algorytmy/2017/08/27/Palindromiczny_podciag/4x-ad028b1da444d7ab904265926948720aa358e5f2-dm-33,33,33-FF,FF,FF.gif)
Dodajemy tu liczby palindromicznych podciągów w przedziałach i
po czym odejmujemy te w przedziale
bo policzyliśmy je podwójnie. Policzyliśmy w ten sposób wszystkie palindromiczne podciągi, które występują też w którymś z krótszych przedziałów. Pozostaje jednak nieuwzględniony przypadek, gdy podciąg zawiera
-tą i
-tą literę - taki podciąg nie występuje ani w
ani w
Skoro
-ta i
-ta litera są pierwszą i ostatnią literą w przedziale, muszą one być równe, by powstał palindrom. Jeśli tak rzeczywiście jest, to do
powinniśmy jeszcze dodać
bo do każdego z podciągów przedziału
możemy teraz dodać
-tą i
-tą literę z przodu i z tyłu, co da nam nowy dłuższy palindrom.
Mówimy, że w palindromie pierwsza litera jest sparowana z ostatnią, druga z przedostatnią itd. Zastanówmy się, jak dla pary indeksów policzyć takie palindromiczne podciągi, które zawierają indeksy
i
a ponadto w nich te dwie litery są ze sobą sparowane. Musi zatem zachodzić równość
a wzięte indeksy z przedziału
muszą tworzyć palindromiczny podciąg. Takich podciągów jest dokładnie
Pozostaje nam jeszcze uwzględnić liczbę możliwych zewnętrznych rozszerzeń, a więc policzyć liczbę takich wyborów, że litery wzięte na lewo od
(te z mniejszymi indeksami) odpowiadają literom wziętym na prawo od
Tę liczbę oznaczmy przez
Za chwilę pokażemy, jak ją obliczać.
Niech oznacza liczbę palindromicznych podciągów, które zawierają indeksy z przedziałów
oraz
a także takich, że litery z
są sparowane z tymi z
(czyli te dwa przedziały zawierają po tyle samo wybranych liter). Podobnie jak do liczenia wartości
możemy zacząć od rekurencyjnego wzoru:
![out[i][ j] = out[i −1][ j]+ out[i][ j+ 1] − out[i− 1][ j +1],](/math/temat/informatyka/algorytmy/2017/08/27/Palindromiczny_podciag/7x-f8fb2ef0f7e585dd3d52d51638bada3d2313719a-dm-33,33,33-FF,FF,FF.gif)
po czym dodać jeśli
Uwzględniamy tu podciągi, które zawierają indeksy z
i
oraz podciągi, które zawierają indeksy z
i
Do obu tych grup podciągów należą takie, które zawierają indeksy z
i
więc takie policzyliśmy dwukrotnie, co musimy odjąć. Dodatkowo, jeśli litery
i
są równe, uwzględniamy podciągi, które je zawierają.
Zauważmy, że w każdym palindromicznym podciągu zawierającym -tą literę, litera ta jest sparowana z dokładnie jedną literą, która musi być, oczywiście, równa
By znaleźć wynik zadania dla
wystarczy więc przeiterować wszystkie indeksy
(
i
) i zsumować iloczyny
(taki iloczyn jest równy liczbie palindromicznych podciągów, w których indeksy
i
są sparowane).
Zarówno obliczenie tablic i
jak i końcowe iterowanie par indeksów, ma złożoność czasową
Tablice
i
mają rozmiar kwadratowy. Czytelnikowi Z Ograniczoną Pamięcią pozostawiamy zastanowienie się nad implementacją w pamięci liniowej.