문제
풀이
- 다이나믹 프로그래밍 문제로 string 2차원 배열을 사용해서 cache와 같이 추가하면 시간초과가 발생한다.
- cache를 갱신시키면서 cache의 경로를 따로 저장하거나, 결과값에서부터 역추적하여 정답에 접근해야 한다.
코드
경로를 저장하는 방법
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int cache[1001][1001];
// 경로를 저장하는 배열
pair<pair<int, int>, char> path[1001][1001];
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(nullptr);
string a;
string b;
cin >> a >> b;
a = '0' + a;
b = '0' + b;
for (int i = 0; i < a.length(); i++)
{
for (int j = 0; j < b.length(); j++)
{
if (i == 0 || j == 0)
{
cache[i][j] = 0;
continue;
}
if (a[i] == b[j])
{
cache[i][j] = cache[i - 1][j - 1] + 1;
// cache가 어디서부터 갱신되었는지 넣고, 문자도 넣는다.
path[i][j] = make_pair(make_pair(i - 1, j - 1), a[i]);
}
else
{
cache[i][j] = max(cache[i - 1][j], cache[i][j - 1]);
// cache가 어디서부터 갱신되었는지 넣는다.
path[i][j] = cache[i - 1][j] > cache[i][j - 1] ? make_pair(make_pair(i - 1, j), ' ')
: make_pair(make_pair(i, j - 1), ' ');
}
}
}
// LCS의 길이
int answer = cache[a.length() - 1][b.length() - 1];
// path의 마지막 부분에서부터 시작한다.
string answer_string;
int x = a.length() - 1;
int y = b.length() - 1;
while (answer_string.size() < answer)
{
// 문자도 추가되었었다면 answer_stirng에 push_back
if (path[x][y].second != ' ')
{
answer_string.push_back(path[x][y].second);
}
// 해당 cache의 부모 cache로 이동
int temp_x = path[x][y].first.first;
int temp_y = path[x][y].first.second;
x = temp_x;
y = temp_y;
}
// 경로는 거꾸로 돌아서 추적했기에 string을 거꾸로 돌린다.
reverse(answer_string.begin(), answer_string.end());
cout << answer << endl;
cout << answer_string;
return 0;
}
역추적하는 방법
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int cache[1001][1001];
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(nullptr);
string a;
string b;
cin >> a >> b;
a = '0' + a;
b = '0' + b;
for (int i = 0; i < a.length(); i++)
{
for (int j = 0; j < b.length(); j++)
{
if (i == 0 || j == 0)
{
cache[i][j] = 0;
continue;
}
if (a[i] == b[j])
{
cache[i][j] = cache[i - 1][j - 1] + 1;
}
else
{
cache[i][j] = max(cache[i - 1][j], cache[i][j - 1]);
}
}
}
int x = a.length() - 1;
int y = b.length() - 1;
// LCS의 길이
int answer = cache[x][y];
string answer_string;
// 마지막 에서부터 역추적
while (cache[x][y])
{
// 위의 행에서부터 온 cache라면 x--
if (cache[x][y] == cache[x - 1][y])
{
x--;
}
// 왼쪽의 열에서부터 온 cache라면 y--
else if (cache[x][y] == cache[x][y - 1])
{
y--;
}
// 대각선에서부터 온 cache라면 answer_string에 추가하고 x--, y--
else
{
answer_string.push_back(a[x]);
x--;
y--;
}
}
// 역추적 했기에 거꾸로 돌린다.
reverse(answer_string.begin(), answer_string.end());
cout << answer << endl;
cout << answer_string;
return 0;
}
'알고리즘 > 백준' 카테고리의 다른 글
[백준][C++] 17404: RGB거리 2 (0) | 2023.10.15 |
---|---|
[백준][C++] 10942: 팰린드롬? (0) | 2023.10.14 |
[백준][C++] 2239: 스도쿠 (0) | 2023.10.12 |
[백준][C++] 1806: 부분합 (0) | 2023.10.11 |
[백준][C++] 1647: 도시 분할 계획 (2) | 2023.10.10 |