Maksymalna konstrukcja podciągów

18

W tym wyzwaniu masz dwie rzeczy:

  1. Długość sznurka, N
  2. Lista ciągów, Lkażda z przypisaną wartością punktową. Każdy ciąg, który nie jest przekazywany, ma wartość punktową 0

Musisz skonstruować ciąg długości N, aby suma wszystkich punktów podłańcuchowych była jak największa.

Na przykład:

5 [("ABC", 3), ("DEF", 4), ("CDG", 2)]

powinien wyjść

ABCDG

Ponieważ dwa podciągi z punktami ( ABCi CDG) mają w sumie 5 punktów, a żadna inna możliwa konstrukcja nie może dać 5 lub więcej punktów.

Podciągi mogą być używane wiele razy w ciągu i mogą się nakładać. Możesz założyć, że punkty będą zawsze dodatnie, długości podciągów będą wynosić od 1 do długości Nznaków i to N > 0. Jeśli wiele konstrukcji jest maksymalnych, wydrukuj dowolną z nich.

Twój program musi działać w rozsądnym czasie (nie więcej niż minuta dla każdego z przykładów):

1 [("A", 7), ("B", 4), ("C", 100)]     => C
2 [("A", 2), ("B", 3), ("AB", 2)]      => AB
2 [("A", 1), ("B", 2), ("CD", 3)]      => BB
2 [("AD", 1), ("B", 2), ("ZB", 3)]     => ZB
3 [("AB", 2), ("BC", 1), ("CA", 3)]    => CAB
3 [("ABC", 4), ("DEF", 4), ("E", 1)]   => DEF
4 [("A", 1), ("BAB", 2), ("ABCD", 3)]  => AAAA or ABAB or BABA or ABCD
5 [("A", 1), ("BAB", 2), ("ABCD", 3)]  => BABCD or BABAB
5 [("ABC", 3), ("DEF", 4), ("CDG", 2)] => ABCDG
5 [("AB", 10), ("BC", 2), ("CA", 2)]   => ABCAB
6 [("AB", 10), ("BC", 2), ("CA", 2)]   => ABABAB
8 [("AA", 3), ("BA", 5)]               => BAAAAAAA
10 [("ABCDE", 19), ("ACEBD",  18), ("ABEDC", 17), ("BCEDA", 16), ("EBDAC", 15), ("BACD", 14), ("CADB", 13), ("ABDC", 12), ("CABD", 11), ("EBDC", 10), ("ACE", 9), ("CBA", 8), ("AEC", 7), ("BE", 6), ("AE", 5), ("DC", 4), ("BA", 3), ("A", 2), ("D", 1)]
=> ACEBDACEBD

To jest , więc przygotuj najkrótszą odpowiedź w swoim ulubionym języku!

Nathan Merrill
źródło
Czy musimy użyć dokładnego formatu wejściowego, czy też możemy użyć wygodnego formatu wejściowego dla naszego języka?
flawr
@ flawr dowolna wygodna metoda wprowadzania danych jest w porządku (słownik, standardowe, parametry funkcji)
Nathan Merrill,
W DEFkrotce brakuje przecinka
isaacg
Mam idealnie fajne rozwiązanie, ale jest zbyt wolne dla ostatniego przypadku testowego.
isaacg,
1
@isaacg Mam eleganckie rozwiązanie, niestety ten komentarz jest zbyt mały, aby go pomieścić. (Nie chcę, chciałem po prostu zacytować Fermata.)
lub

Odpowiedzi:

1

Python 2.7, 503 bajtów

Nie jest to szczególnie gra w golfa, ani nie jest szczególnie wydajne; to tylko stosunkowo skrócone wyliczenie wykonalnych ciągów, które są brutalnie wymuszone. Nie sądzę, że byłoby zbyt trudno stworzyć dopuszczalną heurystykę do użycia z A *, która prawdopodobnie byłaby nieco szybsza. Nie zawracałem sobie tym głowy, ponieważ ta metoda rozwiązuje wszystkie przykłady w około 47 sekund na moim laptopie.

import re
v=lambda l,s:sum([len([m.start() for m in re.finditer('(?=%s)'%u,s)])*v for u,v in l])
def m(n,l,e):
 if len(e)==n:
  yield e
 else:
  u=1
  for s,v in sorted(l,key=lambda j:j[1],reverse=True):
   for i in range(len(s)-1,0,-1):
    if len(e)+len(s)-i <= n and e.endswith(s[:i]):
     for r in m(n,l,e+s[i:]):
      u=0;yield r
   if len(e)+len(s)<=n:
    for r in m(n,l,e+s):
     u=0;yield r
  if u:
   yield e
def p(n,l):
 b,r=-1,0
 for s in m(n,l,''):
  a=v(l,s)
  if a>b:b,r=a,s
 return r

Aby to przetestować:

if __name__ == "__main__":
    for n, l in [
            (1, [("A", 7), ("B", 4), ("C", 100)]),     # => C
            (2, [("A", 2), ("B", 3), ("AB", 2)]),      # => AB
            (2, [("A", 1), ("B", 2), ("CD", 3)]),      # => BB
            (2, [("AD", 1), ("B", 2), ("ZB", 3)]),     # => ZB
            (3, [("AB", 2), ("BC", 1), ("CA", 3)]),    # => CAB
            (3, [("ABC", 4), ("DEF", 4), ("E", 1)]),   # => DEF
            (4, [("A", 1), ("BAB", 2), ("ABCD", 3)]),  # => AAAA or ABAB or BABA or ABCD
            (5, [("A", 1), ("BAB", 2), ("ABCD", 3)]),  # => BABCD or BABAB
            (5, [("ABC", 3), ("DEF", 4), ("CDG", 2)]), # => ABCDG
            (5, [("AB", 10), ("BC", 2), ("CA", 2)]),   # => ABCAB
            (6, [("AB", 10), ("BC", 2), ("CA", 2)]),   # => ABABAB
            (8, [("AA", 3), ("BA", 5)]),               # => BAAAAAAA
            (10, [("ABCDE", 19), ("ACEBD",  18), ("ABEDC", 17), ("BCEDA", 16), ("EBDAC", 15), ("BACD", 14), ("CADB", 13), ("ABDC", 12), ("CABD", 11), ("EBDC", 10), ("ACE", 9), ("CBA", 8), ("AEC", 7), ("BE", 6), ("AE", 5), ("DC", 4), ("BA", 3), ("A", 2), ("D", 1)]) # => ACEBDACEBD
    ]:
        print p(n, l)

Wyjaśnienie

vFunkcja po prostu oblicza wartość danego łańcucha wyszukując wszystkie wystąpienia podciągów w L. mFunkcja wylicza wszystkie ciągi długości nz prefiksem e, który może być generowany z podciągów w l. mrekurencyjnie nazywa się sobą; pierwsza rozmowa powinna przechodzić w ''dla e. Na przykład:

>>> for s in m(4, [("A", 1), ("BAB", 2), ("ABCD", 3)], ''):print s
ABCD
BABA
ABCD
ABAB
AAAA

pFunkcja po prostu pętli przez wszystkie możliwe ciągi (jak wyliczone przez m) i zwraca jedną z najwyższych wartości (jak określono v).

Zauważ, że mfunkcja faktycznie priorytetowo wylicza, sortując na podstawie wartości podciągów. Okazuje się, że nie jest to konieczne do zapewnienia optymalności i faktycznie nieco utrudnia wydajność; Mógłbym zaoszczędzić około 20 bajtów, usuwając go.

ESultanik
źródło