Construção Máxima de Substring

18

Neste desafio, você recebe duas coisas:

  1. Um comprimento de corda, N
  2. Uma lista de strings, Lcada uma com um valor de ponto atribuído. Qualquer string que não é passada tem um valor de ponto 0

Você precisa construir uma sequência de comprimento para Nque a soma de todos os pontos de substring seja o maior possível.

Por exemplo:

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

deve produzir

ABCDG

Como as duas substrings com pontos ( ABCe CDG) têm um total de 5 pontos, e nenhuma outra construção possível pode dar 5 ou mais pontos.

As seqüências de caracteres podem ser usadas várias vezes em uma sequência e podem se sobrepor. Você pode supor que os pontos sempre serão positivos, os comprimentos da substring estarão entre 1 e os Ncaracteres, e isso N > 0. Se várias construções forem máximas, imprima qualquer uma delas.

Seu programa deve ser executado em um período de tempo razoável (não mais que um minuto para cada um dos exemplos):

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

Este é um , então prepare sua resposta mais curta no seu idioma favorito!

Nathan Merrill
fonte
Temos que usar o formato exato de entrada ou podemos usar qualquer formato de entrada conveniente para o nosso idioma?
flawr
@flawr qualquer método conveniente de entrada é bom (dicionário, stdin, parâmetros de função) #
Nathan Merrill
A DEFtupla está faltando uma vírgula
isaacg
Eu tenho uma solução perfeitamente boa, mas é muito lenta para o último caso de teste.
Isaacg
1
@isaacg Eu tenho uma solução elegante, infelizmente esse comentário é muito pequeno para contê-lo. (Eu não, só queria citar Fermat.)
orlp 26/12/15

Respostas:

1

Python 2.7, 503 bytes

Isso não é particularmente jogado, nem é particularmente eficiente; é apenas uma enumeração relativamente condensada de sequências viáveis ​​que são forçadas a bruto. Eu não acho que seria muito difícil criar uma heurística admissível para usar com A *, o que provavelmente seria um pouco mais rápido. Não me incomodei em fazer isso, porque esse método resolve todos os exemplos em cerca de 47 segundos no meu laptop.

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

Para testá-lo:

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)

Explicação

A vfunção simplesmente calcula o valor de uma determinada sequência procurando todas as ocorrências das subseqüências em L. A mfunção enumera todas as seqüências de comprimento ncom prefixo eque pode ser gerado a partir das subseqüências em l. mchama-se recursivamente; a primeira chamada deve passar ''para e. Por exemplo:

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

A pfunção simplesmente percorre todas as seqüências possíveis (conforme enumeradas por m) e retorna a que tiver o valor mais alto (conforme determinado por v).

Observe que a mfunção realmente prioriza a enumeração classificando com base nos valores das substrings. Isso acaba sendo desnecessário para garantir a otimização e realmente atrapalha um pouco a eficiência; Eu poderia salvar ~ 20 ou mais bytes removendo-o.

ESultanik
fonte