Максимальна побудова підрядок


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 будь-який зручний метод введення добре (словник, stdin, параметри функцій)
Nathan Merrill

У DEFкортежі пропущена кома
isaacg

У мене ідеально приємне рішення, але це занадто повільно для останнього тестового випадку.
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 або близько байт, видаливши його.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.