문제 : https://www.acmicpc.net/problem/9252
[알고리즘풀이]
기본적인 틀은 LCS 문제와 같다.
( LCS 기본 문제 : https://travelbeeee.tistory.com/150 )
입력되는 2개의 문자열을 n1, n2 라고 하자. 그리고 다음과 같이 dp배열을 선언해 string과 int를 동시에 담아보자.
pair<string, int> dp[i][j]
dp[i][j].first : n1 의 i번째 문자, n2의 j번째 문자까지 중에서 최장 공통 부분 수열의 문자열.
dp[i][j].second : n1 의 i번째 문자, n2의 j번째 문자까지 중에서 최장 공통 부분 수열의 길이.
1) n1의 i번 째 문자와 n2의 j번 째 문자가 같다면.
dp[i][j].first = dp[i - 1][j - 1].first + n1[i - 1]; // 기존의 가장 큰 문자열에다가 현재 문자를 합쳐준다.
dp[i][j].second = dp[i - 1][j - 1].second + 1; // 기존의 가장 길이에다가 1을 더해준다.
i번 째 문자와 j번 째 문자가 같으므로 그 전인 (i -1)번 째 문자와 (j - 1)번 째 문자까지의 최대 길이에 1을 더해주면 된다.
또, (i - 1)번 째 문자와 (j - 1)번 째 문자까지의 최대 부분 수열에 현재 문자를 더해주면 된다.
2) n1의 i번 째 문자와 n2의 j번 째 문자가 다르다면.
2-1) dp[i - 1][j].second < dp[i][j - 1].second)
dp[i][j] = dp[i][j - 1];
2-2)
dp[i][j] = dp[i - 1][j];
i번 째 문자와 j번 쨰 문자가 다르면 지금 탐색하는 i, j 지점에서 길이가 길어지지 않으므로,
그전까지 탐색해온 값 중 가장 큰 값과 그에 해당하는 문자열을 저장해준다.
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
pair<string, int> dp[1001][1001];
int main(void) {
string n1, n2;
cin >> n1 >> n2;
int n = n1.length(), m = n2.length();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if (n1[i - 1] == n2[j - 1]) {
dp[i][j].first = dp[i - 1][j - 1].first + n1[i - 1];
dp[i][j].second = dp[i - 1][j - 1].second + 1;
}
else {
if (dp[i - 1][j].second < dp[i][j - 1].second)
dp[i][j] = dp[i][j - 1];
else
dp[i][j] = dp[i - 1][j];
}
}
cout << dp[n][m].second << '\n';
cout << dp[n][m].first << '\n';
}
'Problem Solving > BOJ' 카테고리의 다른 글
[BOJ] 11728 : 배열 합치기 -travelbeeee (0) | 2019.10.30 |
---|---|
[BOJ] 1958 : LCS 3 - travelbeeee (0) | 2019.10.29 |
[BOJ] 9251 : LCS - travelbeeee (0) | 2019.10.29 |
[BOJ] 5054 : Optimal Parking - travelbeeee (0) | 2019.10.29 |
[BOJ] 1654 : 랜선 자르기 - travelbeeee (0) | 2019.10.28 |