라떼는말이야

[프로그래머스 lv4] 단어 퍼즐 (DP 풀이) 본문

알고리즘/코딩 테스트

[프로그래머스 lv4] 단어 퍼즐 (DP 풀이)

MangBaam 2021. 9. 12. 20:59
반응형

2017 팁스타운 문제입니다.


문제 설명

단어 퍼즐은 주어진 단어 조각들을 이용해서 주어진 문장을 완성하는 퍼즐입니다. 이때, 주어진 각 단어 조각들은 각각 무한개씩 있다고 가정합니다. 예를 들어 주어진 단어 조각이 [“ba”, “na”, “n”, “a”]인 경우 "ba", "na", "n", "a" 단어 조각이 각각 무한개씩 있습니다. 이때, 만들어야 하는 문장이 “banana”라면 “ba”, “na”, “n”, “a”의 4개를 사용하여 문장을 완성할 수 있지만, “ba”, “na”, “na”의 3개만을 사용해도 “banana”를 완성할 수 있습니다. 사용 가능한 단어 조각들을 담고 있는 배열 strs와 완성해야 하는 문자열 t가 매개변수로 주어질 때, 주어진 문장을 완성하기 위해 사용해야 하는 단어조각 개수의 최솟값을 return 하도록 solution 함수를 완성해 주세요. 만약 주어진 문장을 완성하는 것이 불가능하면 -1을 return 하세요.

제한사항

  • strs는 사용 가능한 단어 조각들이 들어있는 배열로, 길이는 1 이상 100 이하입니다.
  • strs의 각 원소는 사용 가능한 단어조각들이 중복 없이 들어있습니다.
  • 사용 가능한 단어 조각들은 문자열 형태이며, 모든 단어 조각의 길이는 1 이상 5 이하입니다.
  • t는 완성해야 하는 문자열이며 길이는 1 이상 20,000 이하입니다.
  • 모든 문자열은 알파벳 소문자로만 이루어져 있습니다.

입출력 예

입출력 예

입출력 예 설명

입출력 예 #1
문제의 예시와 같습니다.

입출력 예 #2
"ap" 1개, "ple" 1개의 총 2개로 "apple"을 만들 수 있으므로 필요한 단어 개수의 최솟값은 2를 return 합니다.

입출력 예 #3
주어진 단어로는 "banana"를 만들 수 없으므로 -1을 return 합니다.


나의 풀이

처음 풀이한 프로그래머스 4단계 문제이다.

이 문제는 DP로 해결할 수 있다. 작은 부분을 확인하고 작은 부분이 큰 부분에 포함될 수 있는지 확인하는 바텀업 방식이다.

두 번째 예시인 "apple"을 가지고 설명하겠다.  strs = ["app","ap","p","l","e","ple","pp"]

주어진 단어를 뒤에서부터 확인한다.

각 위치 이후의 단어 조각들을 만들 수 있는 최소값을 저장하는 테이블인 d를 선언하고, 무한으로 초기화한다.

▶ "e" 를 확인한다. "e"는 strs에 있으므로 1개의 단어 조각으로 만들 수 있다. d[4]에 1을 기록한다. ("e"의 위치가 4이다)

    "e" 이후에 아무 문자가 없기 때문에 넘어간다.

▶ "l" 을 확인한다. "l"을 확인한다는 것은 "l" 이후의 문자들을 모두 만들 수 있는 경우를 찾는 것이다.

즉, "le"를 만드는 경우를 확인하는 것인데 "l"이 strs에 존재하기 때문에 "e"를 만들 수 있는 경우인 1(d[4]에 기록되어 있음)과 더하면 2가 된다. (이 경우 "le"를 만들 때 "l", "e" 이렇게 두 개의 단어 조각을 사용한 경우이다)

    "l" 이후에 "e"가 있기 때문에 "le"가 strs에 있는지 확인한다. 존재하지 않기 때문에 d[3]은 2가 된다.

▶ "p" 를 확인한다. "p"도 strs에 있으므로 d[2]에다가 d[3]에 저장된 값 + 1을 저장한다. (d[3]에 저장된 값의 의미는 t[3]이후의 문자 조각인 "le"를 만들 수 있는 최소 조각의 개수를 의미한다)

    "pl" 을 만들 수 있는지 확인한다. strs에 존재하지 않기 때문에 넘어간다.

    "ple" 을 만들 수 있는지 확인한다. "ple"는 strs에 존재하기 때문에 d[2]에 저장된 값과 "ple" 이후의 값을 만들 수 있는 경우를 비교해서 더 작은 값을 저장한다. 하지만 "ple" 이후에 단어가 존재하지 않으므로 1이 저장된다.

...

이렇게 마지막까지 수행하면 단어를 만들 수 없는 경우에는 d[0]에는 처음에 초기화한 무한이 들어있을 것이고, 단어를 만들 수 있다면 우리가 구하고자 하는 최소값이 저장되어 있을 것이다.

 

소스 코드

def solution(strs, t):
    INF = int(10e+9) # 충분히 큰 값으로 무한을 표현 # 10,000,000,000
    d = [INF] * len(t) + [0]
    for i in range(len(t)-1, -1, -1):
        for j in range(1, min(6, len(t)-i+1)):
            if t[i:i+j] in strs:
                d[i] = min(d[i], d[i+j]+1)
    return -1 if d[0]==INF else d[0]

정확성 테스트 결과
효율성 테스트 결과

반응형
Comments