Максимальное построение подстроки

18

В этом соревновании вам передаются две вещи:

  1. Длина строки, N
  2. Список строк, Lкаждая с назначенным значением точки. Любая строка, которая не передана, имеет значение 0

Вам нужно построить строку длины Nтак, чтобы сумма всех точек подстроки была как можно большей.

Например:

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

должен выводить

ABCDG

Потому что две подстроки с точками ( ABCи CDG) имеют в общей сложности 5 баллов, и никакая другая возможная конструкция не может дать 5 или более баллов.

Подстроки могут использоваться в строке несколько раз и могут перекрываться. Вы можете предположить, что точки всегда будут положительными, длина подстроки будет от 1 до длин Nсимволов, и это N > 0. Если несколько конструкций максимальны, выведите любую из них.

Ваша программа должна быть запущена за разумное время (не более минуты для каждого из примеров):

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

Это , поэтому подготовьте кратчайший ответ на своем любимом языке!

Натан Меррилл
источник
Нужно ли нам использовать ваш точный формат ввода или мы можем использовать любой удобный формат ввода для нашего языка?
flawr 24.12.15
@ Flawr любой удобный способ ввода в порядке (словарь, стандартный ввод, параметры функции)
Натан Меррилл
DEFКортеж отсутствует запятая
isaacg
У меня есть отличное решение, но оно слишком медленное для последнего теста.
Исаак
1
@isaacg У меня есть элегантное решение, к сожалению, этот комментарий слишком мал, чтобы его содержать. (Не хочу, просто хотел бы процитировать Ферма.)
orlp

Ответы:

1

Python 2.7, 503 байта

Это не особенно игра в гольф, и при этом это не особенно эффективно; это просто относительно сжатое перечисление возможных строк, которые являются грубыми. Я не думаю, что было бы слишком сложно создать допустимую эвристику для использования с A *, что, вероятно, было бы немного быстрее. Однако я не стал этого делать, потому что этот метод решает все примеры за 47 секунд на моем ноутбуке.

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

Чтобы проверить это:

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)

объяснение

vФункция просто вычисляет значение заданной строки путем поиска всех вхождений подстрок в L. mфункция перечисляет все строки длины nс префиксом , eкоторый может быть получен из подстрок в l. mрекурсивно называет себя; первый вызов должен пройти в ''течение e. Например:

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

pФункция просто перебирает все возможные строки (как нумеруются m) и возвращает один с наибольшим значением (как определено v).

Обратите внимание, что mфункция фактически устанавливает приоритеты перечисления путем сортировки на основе значений подстрок. Это оказывается ненужным для обеспечения оптимальности и фактически немного снижает эффективность; Я мог бы сохранить ~ 20 или около того байтов, удалив его.

ESultanik
источник