코딩테스트/C++
[ 백준 BOJ ] 1099번 - 알 수 없는 문장 (C++)
최-코드
2025. 4. 23. 15:55
https://www.acmicpc.net/problem/1099
생각 흐름
- 문제 예제를 보자마자 떠오른 예외 케이스는 abcd, bca, abcd와 같이 주어졌을 때이다. 이 케이스를 떠올리자마자 그리디적으로 접근하면 무조건 틀리겠다고 생각했다.
- 다른 방법이 안 떠올라 dp로 접근해보기로 했다.
- 문제가 풀리게끔 점화식을 생각해보니 dp[i] = dp[a] + b와 같이 할 수 있을 거 같았다. a의 경우는 0부터 i-1까지의 값을 가지고, b의 경우 a 이후의 값부터 i까지에서 가장 적은 비용의 단어를 찾아주면 된다.
- 즉, abcd가 있고 i가 3(d)일 때 0부터 3까지의 단어가 있는지 찾아주고, 이후 dp[0] + bcd, dp[1] + cd, dp[2] + d 중에서 가장 작은 값을 저장하면 된다.
- 성공
#include <iostream>
#include <vector>
#include <string>
#include <memory.h>
#include <unordered_map>
#include <cmath>
using namespace std;
string s;
int N;
vector<string> v[51];
int findAll(int i, int j){
if(v[j-i+1].empty()) return 987654321;
unordered_map<char, int> p;
for(int k = i; k<=j; k++){
p[s[k]]++;
}
int minCost = 987654321;
for(int k = 0; k<v[j-i+1].size(); k++){
int cost = 0;
int reminder = j - i + 1;
unordered_map<char, int> m = p;
for(int h = i; h<=j; h++){
if(m[v[j-i+1][k][h-i]]>0){
m[v[j-i+1][k][h-i]]--;
reminder--;
if(s[h] != v[j-i+1][k][h-i]){
cost++;
}
}else{
cost = 987654321;
break;
}
}
if(reminder>0) continue;
minCost = min(minCost, cost);
}
return minCost;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cin>>s;
cin>>N;
for(int i = 0; i<N; i++){
string tmp;
cin>>tmp;
v[tmp.size()].push_back(tmp);
}
int dp[50];
for(int i = 0; i<50; i++){
dp[i]=987654321;
}
for(int i = 0; i<s.size(); i++){
dp[i] = min(dp[i], findAll(0, i));
for(int j = 0; j<i; j++){
if(dp[j]==987654321) continue;
dp[i] = min(dp[i], dp[j]+findAll(j+1, i));
}
}
if(dp[s.size()-1] == 987654321) cout<<-1<<endl;
else cout<<dp[s.size()-1]<<endl;
return 0;
}