최대 부분 문자열 구성


18

이 도전에서는 두 가지가 전달됩니다.

  1. 끈 길이 N
  2. L각각 포인트 값이 할당 된 문자열 목록 . 전달되지 않은 문자열은 포인트 값이 0입니다.

N모든 부분 문자열 포인트의 합이 최대한 커지도록 길이 문자열을 구성해야 합니다.

예를 들면 다음과 같습니다.

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

출력해야합니다

ABCDG

점 ( ABCCDG)이있는 두 개의 하위 문자열 에는 총 5 개의 점이 있으며 다른 가능한 구성으로는 5 개 이상의 점을 줄 수 없습니다.

하위 문자열은 문자열에서 여러 번 사용할 수 있으며 겹칠 수 있습니다. 점이 항상 양수이고 부분 문자열 길이는 1 ~ N문자 길이 , 그리고 그 사이라고 가정 할 수 있습니다 N > 0. 여러 구성이 최대 인 경우 그 중 하나를 인쇄하십시오.

귀하의 프로그램은 합리적인 시간 내에 실행되어야합니다 (각 예제마다 1 분 이하).

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

@flawr 편리한 입력 방법은 괜찮습니다 (사전, stdin, 함수 매개 변수)
Nathan Merrill

DEF쉼표없는 튜플
isaacg

완벽하게 좋은 해결책이 있지만 마지막 테스트 사례에는 너무 느립니다.
isaacg

1
@isaacg 나는 우아한 해결책을 가지고 있지만 슬프게도이 의견은 그것을 포함하기에 너무 작습니다. (나는 Fermat를 인용하고 싶지 않았다.)
orlp

답변:


1

파이썬 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 바이트 정도를 제거하여 저장할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.