tło
Incydent jest dość nietypowym językiem programowania, ponieważ jego lista tokenów nie jest z góry określona, ale raczej wywodzi się z danych wejściowych. Dlatego tokenizacja programu Incydent może być dość trudna, szczególnie jeśli chcesz to zrobić skutecznie. To zadanie polega na robieniu tego samemu.
Zadanie
Twój program otrzyma ciąg wejściowy. Oto algorytm wykorzystywany przez Incydent do tokenizacji:
- Zidentyfikuj wszystkie ciągi, które występują jako podciąg danych wejściowych na dokładnie trzy sposoby (tj. Są dokładnie trzy wystąpienia tego ciągu w danych wejściowych).
- Odrzucić każdy z tych łańcuchów, które są podłańcuchem innego takiego napisu (np dla wejścia
ababab
, jedyne ciąg byłobyab
, niea
bądźb
, boa
ib
to zarówno podrzędnymiab
). - Odrzuć wszystkie ciągi, które nakładają się na dane wejściowe. (Na przykład
aaaa
zawiera dokładnie trzy kopieaa
, ale kopie te nakładają się na drugi i trzeci znak, więc zostałyby odrzucone. Podobnie, wabababa
, są trzy kopieab
i trzy kopieba
, ale każda z drugiej do szóstej litery jest na nachodzenieab
iba
, tak jakab
iba
byłyby usunięte). - Wszelkie ciągi, które pozostaną w tym momencie, są tokenami używanymi przez program. Tokenizuj oryginalne dane wejściowe w sekwencji tych żetonów (ze względu na odrzucenie w poprzednim kroku będzie tylko jeden sposób, aby to zrobić). Wszelkie znaki na wejściu, które nie są częścią żadnego tokena, są traktowane jako komentarze i odrzucane.
Twój program musi pobrać ciąg jako dane wejściowe i zwrócić odpowiednią tokenizację ciągu (listę tokenów, z których każdy jest wyrażony jako ciąg) jako wynik. Ponadto należy to zrobić co najmniej umiarkowanie skutecznie; w szczególności program musi działać w czasie kwadratowym („O (n²)”) lub lepszym. (Nawiasem mówiąc, prawie na pewno można przejść szybciej niż kwadratowe, ale nie jest to najszybszy algorytm , więc możesz użyć najkrótszego algorytmu, jaki można znaleźć, który mieści się w granicach złożoności.)
Wyjaśnienia
- Chociaż programy incydentów mogą teoretycznie zawierać dowolny z 256 oktetów, dla celów tego wyzwania dopuszczalne jest, aby Twój program obsługiwał tylko dane wejściowe utworzone z drukowalnego ASCII (w tym spacji) oraz znak nowej linii i tabulator. (Wszystkie znane programy incydentów ograniczają się do tego podzbioru). Zauważ, że spacja / nowa linia / tab nie są wyjątkowe i mogą pojawiać się pośrodku tokenów; Incydent traktuje wszystkie 256 oktetów jako nieprzejrzyste.
- Definicja „czasu kwadratowego” brzmi „jeśli rozmiar wejścia zostanie podwojony, program będzie działał wolniej o nie więcej niż stałą plus współczynnik 4”, tj. Jeśli t ( x ) to maksymalny czas, jaki zajmuje Twój program przetworzyć dane wejściowe o rozmiarze x , wtedy musi być pewna stała k, taka, że t (2 x ) <4 t ( x ) + k dla wszystkich x . Pamiętaj, że porównywanie łańcuchów zajmuje czas proporcjonalny do długości łańcuchów.
- Twój program powinien teoretycznie być w stanie obsłużyć programy wejściowe dowolnej długości, jeśli jest uruchamiany w (prawdopodobnie hipotetycznym) wariancie języka, który ma nieograniczoną pamięć i używa nieograniczonych liczb całkowitych (jest OK, jeśli program nie osiągnie tego celu, gdy jest uruchomiony w praktyce z powodu liczby całkowite języka lub pamięć są w rzeczywistości skończone duże). Możesz założyć (w celu obliczenia złożoności), że liczby całkowite, które nie są większe niż długość danych wejściowych, mogą być porównywane w stałym czasie (chociaż pamiętaj, że jeśli użyjesz większych wartości, np. Ze względu na konwersję danych wejściowych na pojedynczej liczby całkowitej, porównanie zajmie dużo czasu proporcjonalnie do liczby cyfr, które mają).
- Możesz użyć dowolnego algorytmu, który mieści się w granicach złożoności, nawet jeśli nie wykonuje on tych samych kroków, co algorytm opublikowany powyżej, pod warunkiem, że daje takie same wyniki.
- Ta łamigłówka dotyczy tokenizacji danych wejściowych, a nie formatowania danych wyjściowych. Jeśli najbardziej naturalny sposób na wyświetlenie listy w twoim języku wymaga niejednoznacznego formatu (np. Rozdzielony znakiem nowej linii, gdy ciągi zawierają dosłowne znaki nowego wiersza lub bez ograniczników między ciągami), nie martw się faktem, że wynik jest niejednoznaczny ( tak długo, jak lista jest faktycznie konstruowana). Możesz chcieć stworzyć drugą wersję swojego zgłoszenia, która generuje jednoznaczne dane wyjściowe, aby pomóc w testowaniu, ale oryginalna wersja jest wersją, która liczy się do oceny.
Przypadek testowy
Dla następującego ciągu wejściowego:
aaabcbcbcdefdfefedghijghighjkllkklmmmmonono-nonppqpq-pqprsrsrstststuvuvu
twój program powinien wygenerować następującą listę wyników:
a a a bc bc bc d e f d f e f e d gh gh gh k l l k k l pq pq pq u u u
Warunek zwycięstwa
Jest to kod-golf , więc wygrywa najkrótszy prawidłowy (tj. Prawidłowe zachowanie wejścia / wyjścia i wystarczająco szybki do wykonania) program, mierzony w bajtach.