https://www.acmicpc.net/problem/1099
1099번: 알 수 없는 문장
첫째 줄에 문장이 주어진다. 문장의 길이는 최대 50이다. 둘째 줄에 단어의 개수 N이 주어지며, N은 50보다 작거나 같은 자연수이다. 셋째 줄부터 N개의 줄에 각 단어가 주어진다. 단어의 길이는 최
www.acmicpc.net
[난이도] Gold3
[유형] DP
[풀이]
단어의 개수와 길이가 50으로 작기 때문에 다이나믹 프로그래밍으로 해결이 가능합니다.
dp 배열은 다음과 같이 정의가 가능하며
dp[n] : 문장 string을 s라고 했을 때, s[n~s.size()-1] 인 substring을 해석하기 위해 필요한 최소 연산
점화식은 다음과 같습니다.
dp[n] = dp[i+1] + [s[n~i]인 substring을 해석하는데 필요한 cost] ( n<=i<s.size()-1)
모든 N개의 단어를 substring s[n~i]으로 변환하는데 드는 cost 중 최솟값을 위의 cost로 사용하면 됩니다.
아래 코드에서는 일단 비교하는 두 string을 정렬하여 비교함으로써 정확히 같은
문자들을 가지고 있는지 확인하였고, 원본 string을 다시 비교하면서 위치가 다른 문자들의 개수를 세서
전체 문자 길이에서 빼주었습니다.
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
string s,word[50];
int dp[51],N,inf=9e8;
int cost(string a,string b){
if(a.size()!=b.size()) return inf;
string ta = a;
string tb = b;
sort(ta.begin(),ta.end());
sort(tb.begin(),tb.end());
if(ta!=tb) return inf;
int ret = a.size();
for(int i=0;i<a.size();i++){
if(a[i]==b[i]) ret--;
}
return ret;
}
int minCost(string k){
int ret = inf;
for(int i=0;i<N;i++) ret = min(ret,cost(k,word[i]));
return ret;
}
int sol(int n){
if(n==s.size()) return 0;
int& ret = dp[n];
if(ret!=-1) return ret;
ret = inf;
for(int i=n;i<s.size();i++){
string k = s.substr(n,i-n+1);
int c = minCost(k);
if(c==inf) continue;
ret = min(ret,c+sol(i+1));
}
return ret;
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(0);
cin >> s >> N;
for(int i=0;i<N;i++) cin >> word[i];
memset(dp,-1,sizeof(dp));
printf("%d",sol(0)==inf ? -1 : sol(0));
}
https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold3/1099.cpp
'Problem-Solving > BOJ' 카테고리의 다른 글
[BOJ/백준][Gold4] 1407 : 2로 몇 번 나누어질까 (C++) (0) | 2021.10.18 |
---|---|
[BOJ/백준][Gold4] 1082 : 방 번호 (C++) (0) | 2021.10.18 |
[BOJ/백준][Gold3] 2571 : 색종이 - 3 (C++) (0) | 2021.10.18 |
[BOJ/백준][Gold3] 2513 : 통학버스 (C++) (0) | 2021.10.18 |
[BOJ/백준][Gold3] 19535 : ㄷㄷㄷㅈ (C++) (0) | 2021.10.18 |