Biorąc pod uwagę listę ciągów, s_0, s_1, ..., s_n
znajdź najkrótszy ciąg, S
który zawiera każdy z nich s_0, s_1, ..., s_n
jako podłańcuch .
Przykłady :
S('LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE')='SEDOLOREMAGNAD'
S('ABCDE', 'BCD', 'C')='ABCDE'
Napisz najkrótszy program (lub funkcję), który rozwiązuje ten problem. Jeśli chcesz, możesz reprezentować ciągi jako tablice lub listy znaków / liczb całkowitych. Standardowe biblioteki są w porządku. Do wejścia / wyjścia można użyć cokolwiek bardziej dogodnego: STDIN / STDOUT, monit użytkownika, parametr / wartość zwracana funkcji itp.
Wydajność nie jest krytyczna - powiedzmy, że dla danych wejściowych o całkowitej długości <100 znaków wynik musi być obliczony średnio w <10 sekund przeciętnie nowoczesnego sprzętu.
Odpowiedzi:
Python 2,
170153/157/159Skrócone dzięki niektórym pomysłom Baptiste .
Drugi podział linii nie jest potrzebny.
Wejście:
'LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE'
Wyjście:
SEDOLOREMAGNAD
Nawet przy długich ciągach wejściowych, działa to w mniej niż 2 sekundy, jeśli jest co najwyżej 7 ciągów wejściowych (jak w podanym przykładzie, który działa na
1,71,5 sekundy na mojej maszynie). Przy 8 lub więcej ciągach wejściowych zajmuje to jednak więcej niż 10 sekund, ponieważ złożoność czasu jestO(n!)
.Jak zauważył Baptiste,
range(99)
należy go zastąpić,range(len(w))
jeśli należy obsługiwać dowolne długości wejściowe (łączna długość kodu to 157 znaków). Jeśli powinny być obsługiwane puste ciągi wejściowe, należy je zmienić narange(len(w)+1)
. Myślę jednak, żerange(99)
działa poprawnie dla dowolnej całkowitej długości wejściowej mniejszej niż 200.Więcej testów:
źródło
Mathematica
337 418372Po bezskutecznych próbach implementacji przy użyciu Mathematica
LongestCommonSubsequencePositions
, przeszedłem do dopasowywania wzorców.Reguła dopasowywania wzorców,
pobiera uporządkowaną parę słów (przedstawionych jako listy znaków) i zwraca: (1) słowa,
{a,y}
a{y,b}
następnie (2) wspólny podłańcuchy
, który łączy koniec jednego słowa z początkiem drugiego słowa, i, wreszcie połączone słowo{a,y,b}
, które zastąpi słowa wejściowe. Zobacz pokrewny przykład Belizariusza: /mathematica/6144/looking-for-longest-common-substring-solutionTrzy kolejne znaki podkreślenia oznaczają, że element jest sekwencją zero lub więcej znaków.
Reverse
jest zatrudniony później, aby zapewnić przetestowanie obu zamówień. Te pary, które mają wspólne litery, są zwracane w niezmienionej formie i ignorowane.Edytuj :
Poniższe słowa usuwają z listy słowa, które są „zakopane” (tj. W pełni zawarte) w innym słowie (w odpowiedzi na komentarz @ flornquake).
Przykład :
zwraca
Stosowanie
źródło
"LOREM", "ORE", "R"
?"LOREM"
?)GolfScript, 66 znaków
Dość krótki, ale ze względu na wykładniczą złożoność czasu (i GolfScript) naprawdę powolny, przekracza limit 10 sekund.
Przykłady:
źródło
Python 2,
203187200Wejście:
['LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE']
Wyjście:
SEDOLOREMAGNAD
Edytować
Używając
reduce
i trochę brudnych sztuczek związanych z importowaniem, mogę to jeszcze bardziej zmniejszyć (i tylko do jednej linii!):Edytuj 2
Jak zauważono trzęsienie ziemi, daje to nieprawidłowe wyniki, gdy jedno słowo jest zawarte w innym. Poprawka tego dodaje kolejne 13 znaków:
Oto oczyszczona wersja:
Możliwe jest ogolenie kilku postaci kosztem poprawności teoretycznej za pomocą
range(99)
zamiastrange(len(x))
(kredyty do trzęsienia ziemi za myślenie o tym).źródło
'LOREM', 'ORE', 'R'
niepoprawnie generuje wynikLOREMORER
.Python, 144 znaki
S
pobiera zestaw słów,A
które nadal wymagają umieszczenia, oraz ciągs
zawierający słowa umieszczone do tej pory. Odbieramy pozostały słowoa
odA
i pokrywają ją od0
dolen(a)
znaków z końcems
.Podany przykład zajmuje tylko około 0,15 sekundy.
źródło
['LOREM', 'ORE', 'R']
. Pozwoliłem sobie to naprawić i jeszcze bardziej pograć w swoje rozwiązanie:S=lambda A,s='':A and min((S(A-{a},(s+a[max(i*(s[-i:]==a[:i])for i in range(len(a))):],s)[a in s])for a in A),key=len)or s
(druga linia nie jest potrzebna). Użycie:S({'LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE'})
zwraca'SEDOLOREMAGNAD'
.Haskell, 121
Minus dwa, jeśli funkcja nie musi być powiązana z nazwą
źródło