Informatyczny kącik olimpijski
Cyfrowy ciąg
W tym odcinku omówimy rozwiązanie zadania "Cyfrowy ciąg", które pojawiło się w eliminacjach do zawodów Romanian Master of Informatics.
Zadanie (Cyfrowy ciąg). Tadek napisał ciąg
złożony z
cyfr od
do
Chciałby podzielić ten ciąg na
spójnych fragmentów. Każdy fragment czytany od lewej do prawej tworzy liczbę. Tadek chciałby dokonać takiego podziału, aby największa z
otrzymanych liczb była jak najmniejsza.
Niech
oznacza fragment 
Zauważmy, że
zawiera tylko cyfry od
do
- nie ma cyfry
Zatem dowolny jego fragment opisuje liczbę bez zer wiodących. Od tego momentu zakładamy, że rozważamy tylko liczby bez zer wiodących. Wiadomo, że dłuższa liczba jest większa niż krótsza. W związku z tym chcemy tak podzielić ciąg, aby największa liczba była możliwie najkrótsza. Największa liczba zawiera przynajmniej
cyfr. Zauważmy, że w jakimś optymalnym podziale będą wyłącznie liczby
-cyfrowe lub
-cyfrowe. Dokładniej, w jakimś optymalnym podziale będzie:
liczb
-cyfrowych, gdzie
jeśli
i
w przeciwnym przypadku,
liczb
-cyfrowych, gdzie 
Niech
oraz
Szukamy takiego podziału
na
liczb
-cyfrowych i
liczb
-cyfrowych, żeby największa liczba była jak najmniejsza.
Rozwiązanie 
Ten problem możemy rozwiązać za pomocą metody programowania dynamicznego. Otóż niech
oznacza wartość największej liczby w optymalnym podziale
pierwszych cyfr ciągu na
liczb
-cyfrowych oraz
liczb
-cyfrowych. Wyznaczymy wartości
dla wszystkich takich
że
oraz
Wówczas wynikiem będzie
Niech
zaś ![P[i][ j]=min(p,p) |D 12](/math/temat/informatyka/algorytmy/2019/11/29/Cyfrowy_ciag/14x-bcb97a70b729f7d5b1b3942f76c74d1ac36840ba-im-33,33,33-FF,FF,FF.gif)
dla
gdzie:
to wynik podziału przy założeniu, że ostatnia liczba ma
cyfr. Wtedy
jeśli 
i
w przeciwnym przypadku.
to wynik podziału przy założeniu, że ostatnia liczba ma
cyfr. Wtedy
jeśli 
i
w przeciwnym przypadku.
Mamy
liczb "dłuższych" oraz
liczb "krótszych", czyli wszystkich stanów do obliczenia jest
Obliczenie jednego stanu zajmuje
(porównanie dwóch liczb długości
). Zatem całe rozwiązanie działa w czasie 
Rozwiązanie 
W tym rozwiązaniu wykorzystamy algorytm wyszukiwania binarnego. Wiemy, że wynikiem jest wartość jakiegoś podsłowa długości
W pierwszej fazie rozwiązania weźmy wszystkie
-cyfrowe podsłowa i uporządkujmy je niemalejąco. Takich liczb jest
Ich posortowanie wymaga
porównań, zaś jedno porównanie zajmuje czas
Zatem pierwsza faza działa w czasie 
Kiedy mamy już uporządkowany ciąg i wiemy, że jedna z tych liczb jest wynikiem, to możemy wykonać w tym ciągu wyszukiwanie binarne - drugą fazę rozwiązania. Załóżmy, że w kroku algorytmu sprawdzamy, czy wynik jest nie większy niż
Zatem chcemy dowiedzieć się, czy istnieje podział ciągu na co najwyżej
liczb nie większych niż
W tym celu będziemy dokonywali podziału od lewej do prawej. W każdym kroku zachłannie wybieramy największą możliwą liczbę. Jeśli liczba tworzona przez
kolejnych cyfr jest nie większa niż
to dodajemy ją do podziału. W przeciwnym przypadku dodajemy liczbę o jeden krótszą. Jeśli po
krokach wykorzystamy wszystkie cyfry, to znaleźliśmy podział o wyniku co najwyżej 
Algorytm wyszukiwania binarnego wykona
kroków. W każdym kroku przechodzimy po całym ciągu, co zajmuje
operacji. Zatem druga faza działa w czasie
a w całym rozwiązaniu wykonuje się
operacji.
Rozwiązanie 
Spróbujmy przyspieszyć pierwszą fazę poprzedniego rozwiązania. W tym celu wykorzystamy słownik podsłów bazowych, którego konstrukcja wymaga
operacji. Za pomocą tej struktury danych możemy w czasie
porównać leksykograficznie dwa podsłowa, co jest równoważne porównaniu wartości liczbowych przez nie reprezentowanych. A więc pierwszą fazę rozwiązania wykonujemy w czasie 
Wersja trudniejsza - cyfry na okręgu
Dla ambitnych Czytelników proponujemy trudniejszą wersję zadania - cyfry są ułożone na okręgu, który możemy rozciąć w dowolnym miejscu. Przedstawimy krótki zarys rozwiązania. Zduplikujmy ciąg
sklejając dwie jego kopie. W ten sposób każde podsłowo długości
opisuje jakąś rotację cykliczną
Wynik będziemy wyszukiwali binarnie (jak w poprzednim rozwiązaniu). W każdym kroku, dla każdej pozycji wyznaczamy najdalszą pozycję na prawo, gdzie może zaczynać się kolejna liczba. Jeśli pozycje zinterpretujemy jako wierzchołki, a przejścia do kolejnych liczb jako krawędzie, to otrzymamy graf acykliczny. Pytamy, czy w takim grafie istnieje
-krawędziowa ścieżka, która pokrywa
liter. Można to sprawdzić metodą skoków potęgami dwójki.