거의 알고리즘 일기장

백준 16500번 _ 문자열 판별 본문

알고리즘 문제풀이

백준 16500번 _ 문자열 판별

건우권 2020. 5. 10. 19:05

https://www.acmicpc.net/problem/16500

 

16500번: 문자열 판별

첫째 줄에 길이가 100이하인 문자열 S가 주어진다. 둘째 줄에는 A에 포함된 문자열의 개수 N(1 ≤ N ≤ 100)이 주어진다. 셋째 줄부터 N개의 줄에는 A에 포함된 단어가 한 줄에 하나씩 주어진다. A에 포함된 문자열은 알파벳 소문자로만 이루어져 있고, 길이는 100을 넘지 않는다.

www.acmicpc.net

 접근

 이 문제를 완전탐색으로 푼다면 최악의 경우 100!으로 절대 시간안에 풀수없다. 

 잘 보면 중복연산이 매우매우 많으니 메모제이션을 사용하자!! 


 풀이방법

 이 문제는 주어진 word들이 S를 만들수 있는지 없는지만 판별하면 되는 문제다.

 그러므로 dp[string 길이] : -1일땐 아직 탐색안한것, 0일땐 탐색했는데 없는것, 1일때 탐색했는데 있는것 이렇게 세가지 형태로 두겠다. 그 이후에는 그냥 일반적인 top down 방식 ( 재귀방식 )으로 풀면 된다. 밑의 코드를 보면 일반적으로 자주쓰는 형태라는것을 알수있다. 자세하게 설명하기엔 전에 풀었던 문제들과 코딩형태가 너무 유사해서 생략했다.

int getPossibleOrNot(int pos)
{
	int& ret = dp[pos];
	if (ret != -1) return ret;

	//기저사례 : 여기까지 무사히 왔으면 있는겨
	if (pos == S.size()) return ret = 1;

	ret = 0;
	for (int i = 1; i <= N; i++)
	{
		if (compareEachOther(i, pos) == false)
			continue;
		int nextPos = pos + words[i].size();
		ret = max(ret, getPossibleOrNot(nextPos));
	}
	return ret;
}

 

 확실한 풀이를 보고싶다면 밑의 풀이에서 완전탐색부터 시작해서 재귀방식으로 푸는것까지 자세하게 풀어놓았으니 이걸 보면 좋겠다. 잘 보면 거의 유사하다

https://kunkunwoo.tistory.com/80

 

알고스팟_ 와일드 카드_ 종만북_DP

https://www.algospot.com/judge/problem/read/WILDCARD algospot.com :: WILDCARD Wildcard 문제 정보 문제 와일드카드는 다양한 운영체제에서 파일 이름의 일부만으로 파일 이름을 지정하는 방법이다. 와일드카..

kunkunwoo.tistory.com


 전체코드

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int dp[101];
string S;
string words[101];
int N;

void dpInit()
{
	for (int i = 0; i <= S.size(); i++)
		dp[i] = -1;
}

void Input()
{
	cin >> S;
	cin >> N;
	for (int i = 1; i <= N; i++)
		cin >> words[i];
}

bool compareEachOther(const int& wordIdx, const int& pos)
{
	int wordSize = words[wordIdx].size();
	//word가 남은 문장보다 길면 당연히 false
	if (wordSize > S.size() - pos)
		return false;

	//비교 ㄱㄱ
	string word = words[wordIdx];
	for (int i = 0; i < wordSize; i++)
		if (word[i] != S[pos + i])
			return false;
	return true;
}

int getPossibleOrNot(int pos)
{
	int& ret = dp[pos];
	if (ret != -1) return ret;

	//기저사례 : 여기까지 무사히 왔으면 있는겨
	if (pos == S.size()) return ret = 1;

	ret = 0;
	for (int i = 1; i <= N; i++)
	{
		if (compareEachOther(i, pos) == false)
			continue;
		int nextPos = pos + words[i].size();
		ret = max(ret, getPossibleOrNot(nextPos));
	}
	return ret;
}

int main()
{
	Input();
	dpInit();
	cout << getPossibleOrNot(0);
	return 0;
}

 후기

 처음에는 어떻게 접근해야 할지 엄청 막막했다. 하지만 잘 보니까 종만북에서 자주보던 dp풀이로 풀수있을것같아서 그렇게 풀어보았다. 

반응형

'알고리즘 문제풀이' 카테고리의 다른 글

Codeforces Round #582 (Div. 3), (A,B,C) review  (0) 2020.05.11
백준 11055, 1149  (0) 2020.05.10
백준 12865번 _ 평범한 배낭  (0) 2020.05.10
백준 11051번 _ 이항 계수2  (0) 2020.05.09
백준 11057번 _ 오르막 수  (0) 2020.05.09
Comments