본문 바로가기

알고리즘/프로그래머스

프로그래머스 - 단어 퍼즐(Level 4)/Wanna Be 컴잘알

728x90

문제 출처 - https://programmers.co.kr/learn/courses/30/lessons/12983#

 

코딩테스트 연습 - 단어 퍼즐 | 프로그래머스

단어 퍼즐은 주어진 단어 조각들을 이용해서 주어진 문장을 완성하는 퍼즐입니다. 이때, 주어진 각 단어 조각들은 각각 무한개씩 있다고 가정합니다. 예를 들어 주어진 단어 조각이 [“ba”, “na”, “n”, “a”]인 경우 ba, na, n, a 단어 조각이 각각 무한개씩 있습니다. 이때, 만들어야 하는 문장이 “banana”라면 “ba”, “na”, “n”, “a”의 4개를 사용하여 문장을 완성할 수 있지만, “ba”, “na”, “na”의 3개만을 사

programmers.co.kr

 

-문제-

 

단어 퍼즐은 주어진 단어 조각들을 이용해서 주어진 문장을 완성하는 퍼즐입니다. 이때, 주어진 각 단어 조각들은 각각 무한개씩 있다고 가정합니다. 예를 들어 주어진 단어 조각이 [“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 이하입니다.
  • 모든 문자열은 알파벳 소문자로만 이루어져 있습니다.

입출력 예

strs t result
[ba,na,n,a] banana 3
[app,ap,p,l,e,ple,pp] apple 2
[ba,an,nan,ban,n] banana -1

 

입출력 예 설명

 

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

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

 

-접근법-

 

1. string t 을 문자 단위로 비교해본다. strs =[app,ap,p,l,e,ple,pp], t = apple같은 경우 t[0]=a이므로 strs안에 a로 끝나는 문자열이 있는지 확인해본다. a로 끝나는 문자열이 없으므로  dp[0]=t.size()+1으로 갱신. (여기서 t.size()+1은 문자열을 만들 수 없는 최대값이다.)

 

t[1] = p 이므로 p로 끝나는 문자열은 app, ap, p, pp가 있다. 이경우 문자열 비교를 해보면 올 수있는 부분문자열은 ap밖에없다. 따라서 dp[1] = 1

t[2] = p 이므로 p로 끝나는 문자열은 app, ap, p, pp가 있고 이경우 문자열 비교를 해보면 올 수있는 부분문자열은 app,p, pp가 있다. app라면 경우는 dp[2]=1이되고, p라면 dp[2]=dp[1]+1=2, pp라면 dp[2]=dp[0]+1=7이된다.

최소를 선택해야하므로 app를 선택한 dp[2]=1이다. 

 

2. 바로 이해 안 될 수 있지만 1번의 흐름을 이해하고 1번 같은 방법으로 문자열 끝까지 반복하면 dp[t.size()-1]의 값이 답이됩니다. (단, t.size()보다 클 경우 만들 수 없는 경우이므로 -1을 return)

 

-코드-

#include <iostream>
#include <string>
#include <vector>
using namespace std;

//주어진 것으로 못만들면 -1을 return
// t는 1이상 20,000 이하

int dp[20000];

int solution(vector<string> strs, string t)
{
	int answer = 0;
	
	for (int p = 0; p < t.size(); p++) {

		int index = p;
		char c = t[p];
		dp[index] = t.size() + 1; //디폴트값, 만들 수 없는 최대값

		for (int i = 0; i < strs.size(); i++) {
			bool same = true;
			int length = strs[i].size() - 1;
			if (strs[i][length] == c) { //마지막 문자가 같을 때

				for (int k = 0; k <= length; k++) { // 부분 문자열 비교
					if (t[index - k] != strs[i][length - k]) {
						same = false;
						break;
					}
				}

				if (same) { //부분 문자열이다.
					if (index - length - 1 == -1) { // 시작지점일때
						dp[index] = 1;
					}
					else {// 시작지점이아니면 최소값을 찾아 dp에 갱신
						if (dp[index - length - 1] + 1 < dp[index]) { 
							dp[index] = dp[index - length - 1] + 1;
						}
					}
				}
			}
		}
	}


	answer = dp[t.size() - 1];
	if (answer >= t.size()+1) {
		answer = -1;
	}


	return answer;
}
728x90