https://www.acmicpc.net/problem/9252
해당 문제는 다이나믹 프로그래밍 문제로, 1 ~ n 인덱스까지의 A 문자열이 있을 때, 1 ~ n 인덱스까지의 B 문자열과의 최장 공통 수열을 2차원 dp 배열에 차례대로 갱신하는 Bottom-Up 방식으로 풀었다.
1) A 문자열의 길이가 n이고, B 문자열의 길이가 m이라고 할 때, dp[n][m]에는 A 문자열과 B 문자열 사이의 최장 증가 수열의 길이가 저장된다. 따라서 이 dp[n][m]까지 오는 경로를 역추적하면 최장 증가 수열이 어떤 문자로 구성되어있는지 알 수 있다.
2) 변수 i
, j
를 선언하고, 각각 n과 m으로 초기화한다. 또한 최장 증가 수열을 저장할 문자열 변수 answer
를 선언한다.
3) i와 j가 모두 0이 될 때까지 아래 과정을 반복한다.
i
와 j
를 1씩 감소시키고, answer
에 str1[i](현재 순서 글자)를 추가한다.i
를 1 감소시킨다.j
를 1 감소시킨다.4) answer
에 최장 증가 수열이 뒤집힌 상태로 저장되어있으므로, 이를 반대로 출력한다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int n, m;
int dp[1001][1001];
string str1, str2, answer;
void solution()
{
int maxCount = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if (str1[i - 1] == str2[j - 1])
{
dp[i][j] = dp[i - 1][j - 1] + 1;
if (maxCount < dp[i][j])
{
maxCount = dp[i][j];
}
}
else
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
cout << dp[n][m] << endl;
int i = n, j = m;
while (i != 0 && j != 0)
{
if (str1[i - 1] == str2[j - 1])
{
answer += str1[i - 1];
i--;
j--;
}
else
{
if (dp[i][j] == dp[i - 1][j])
i--;
else if (dp[i][j] == dp[i][j - 1])
j--;
}
}
for(int i = answer.length() - 1; i >= 0; i--)
cout << answer[i];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
cin >> str1;
cin >> str2;
n = str1.size();
m = str2.size();
solution();
}