Wprowadzenie
Więc marnuję swój czas, ponownie badając algorytmy sortowania sufiksów, oceniając nowe pomysły ręcznie i w kodzie. Ale zawsze staram się zapamiętać rodzaj moich sufiksów! Czy możesz mi powiedzieć, jakiego typu są moje sufiksy?
Najbardziej lewe co?
Wiele algorytmów sortowania sufiksów (SAIS, KA, mój własny daware) grupuje sufiksy do różnych typów w celu ich posortowania. Istnieją dwa podstawowe typy: typu S i L typu przyrostki. Sufiksy typu S to sufiksy, które są leksykograficznie mniejsze ( S maller) niż następujący sufiks i typ L, jeśli jest leksykograficznie większy ( L arger). Najbardziej lewy typ S ( typ LMS ) to po prostu: sufiks typu S poprzedzony sufiksem typu L.
Cechą szczególną tych sufiksów typu LMS jest to, że po ich posortowaniu możemy posortować wszystkie pozostałe sufiksy w czasie liniowym! Czy to nie jest niesamowite?
Wyzwanie
Podany ciąg znaków zakłada, że jest zakończony znakiem specjalnym, który jest mniejszy niż jakikolwiek inny znak w tym ciągu (np. Mniejszy niż nawet bajt zerowy). Wypisuje znak typu corrosponding dla każdego przyrostka.
Można dowolnie wybrać, które char do użytku, do którego typu, ale wolałbym L, S and *
na L-, S- and LMS-type
tak długo, jak są one wszystkie do druku ( 0x20 - 0x7E
).
Przykład
Biorąc pod uwagę ciąg mmiissiissiippi
wyjściowy (przy użyciu L, S and *
):
LL*SLL*SLL*SLLL
Na przykład pierwszy L
wynika z faktu, że mmiissiissiippi$
jest leksykograficznie większy niż miissiissiippi$
( $
reprezentuje dodany minimalny znak):
L - mmiissiissiippi$ > miissiissiippi$
L - miissiissiippi$ > iissiissiippi$
* - iissiissiippi$ < issiissiippi and preceeded by L
S - issiissiippi$ < ssiissiippi$
L - ssiissiippi$ > siissiippi$
L - siissiippi$ > iissiippi$
* - iissiippi$ < issiippi$ and preceeded by L
S - issiippi$ < ssiippi$
L - ssiippi$ > siippi$
L - siippi$ > iippi$
* - iippi$ < ippi$ and preceeded by L
S - ippi$ < ppi$
L - ppi$ > pi$
L - pi$ > i$
L - i$ > $
Kilka innych przykładów:
"hello world" -> "L*SSL*L*LLL"
"Hello World" -> "SSSSL*SSLLL"
"53Ab§%5qS" -> "L*SSL*SLL"
Cel
Nie jestem tu po to, by drażnić Petera Cordesa (kiedyś zrobię to przy przepełnieniu stosu); Jestem po prostu bardzo leniwy, więc to jest oczywiście golf golfowy ! Najkrótsza odpowiedź w bajtach wygrywa.
Edycja: Kolejność znaków jest podana według wartości bajtów. Oznacza to porównanie powinno być jak C użytkownika strcmp
.
Edycja2: Jak podano w komentarzach, wyjście powinno być pojedynczym znakiem dla każdego znaku wejściowego. Chociaż założyłem, że byłoby to rozumiane jako „zwróć ciąg”, wydaje się, że co najmniej 1 odpowiedź zwraca listę pojedynczych znaków. Aby nie unieważniać istniejących odpowiedzi, pozwolę ci zwrócić listę pojedynczych znaków (lub liczb całkowitych, które po wydrukowaniu dają tylko 1 znak).
Wskazówki dotyczące czasu liniowego:
- Można to zrobić w 2 równoległych iteracjach do przodu lub w jednej iteracji do tyłu.
- Stan każdego sufiksu zależy tylko od pierwszych 2 znaków i rodzaju drugiego.
- Skanując dane wejściowe w odwrotnym kierunku, możesz określić L lub S w następujący sposób:
$t=$c<=>$d?:$t
(PHP 7), gdzie$c
jest obecny znak$d
poprzedniego i$t
poprzedniego typu. - Zobacz moją odpowiedź na PHP . Jutro przyznam nagrodę.
c++
ciągów stylów. Pomyśl o tym jak o danych binarnych.
*
znaczy
*
oznacza, że odpowiedni sufiks jest typu left most s-type
. A S-type suffix that is preceeded by a L-type suffix.
.