넘치게 채우기

[BOJ] 9252 - LCS 2 본문

PS/BOJ

[BOJ] 9252 - LCS 2

riveroverflow 2024. 12. 27. 15:59
728x90
반응형

https://www.acmicpc.net/problem/9252

BOJ - LCS 2

문제 유형: LCS(Longest Common Subsequence), 다이나믹 프로그래밍, 문자열처리

문제 난이도: Gold IV

시간 제한: 1초

메모리 제한: 256MB

 

문제

LCS(Longest Common Subsequence, 최장 공통 부분 수열)문제는 두 수열이 주어졌을 때, 모두의 부분 수열이 되는 수열 중 가장 긴 것을 찾는 문제이다.

예를 들어, ACAYKP와 CAPCAK의 LCS는 ACAK가 된다.

 

입력

첫째 줄과 둘째 줄에 두 문자열이 주어진다. 문자열은 알파벳 대문자로만 이루어져 있으며, 최대 1000글자로 이루어져 있다.

 

출력

첫째 줄에 입력으로 주어진 두 문자열의 LCS의 길이를, 둘째 줄에 LCS를 출력한다.

LCS가 여러 가지인 경우에는 아무거나 출력하고, LCS의 길이가 0인 경우에는 둘째 줄을 출력하지 않는다.

 

풀이

dp[i][j] = 첫 문자열의 i-1인덱스와 두 번째 문자열의 j-1번째 인덱스를 읽고 난 뒤의 LCS길이로 한다.

dp[0][*]과 dp[*][0]은 빈 문자열과의 비교로, 0이다.

s1[i-1] == s2[j-1]가 같다면 dp[i][j] = dp[i-1][j-1] + 1이다.

그러나 다르다면, dp[i-1][j]와 dp[i][j-1]중 더 긴 길이로 한다.

 

이제, dp[n][m]에는 s1과 s2의 LCS의 길이가 저장되어있다.

이제, 역추적으로 i = n, j = m부터 시작한다.

s1[i-1]랑 s2[j-1]가 같다면, 문자열에 문자를 추가하고 i와 j 둘다 1씩 줄인다.

아니라면, dp[i-1][j]나 dp[i][j-1]중에서 더 긴 쪽으로 i나 j 둘 중 하나만 1씩 줄인다.

이렇게 두 인덱스 중 다시 0으로 돌아올때까지 한다.

 

이러면, 문자열에는 LCS의 역문자열이 남아있다.

LCS를 뒤집어서 출력한다.

 

코드

C++

#include <bits/stdc++.h>
using namespace std;

int n, m;
string s1, s2;

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);

  cin >> s1 >> s2;
  n = s1.size();
  m = s2.size();

  vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= m; ++j) {
      if (s1[i - 1] == s2[j - 1]) {
        dp[i][j] = dp[i - 1][j - 1] + 1;
      } else {
        dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
      }
    }
  }

  cout << dp[n][m] << "\n";

  int i = n, j = m;
  string lcs = "";
  while (i > 0 && j > 0) {
    if (s1[i - 1] == s2[j - 1]) {
      lcs += s1[i - 1];
      i--;
      j--;
    } else if (dp[i - 1][j] >= dp[i][j - 1]) {
      i--;
    } else {
      j--;
    }
  }

  reverse(lcs.begin(), lcs.end());
  cout << lcs << "\n";

  return 0;
}
728x90
반응형

'PS > BOJ' 카테고리의 다른 글

[BOJ] 17404 - RGB거리 2  (0) 2024.12.29
[BOJ] 10942 - 팰린드롬?  (0) 2024.12.28
[BOJ] 18353 - 병사 배치하기  (0) 2024.12.26
[BOJ] 6118 - 숨바꼭질  (0) 2024.12.25
[BOJ] 1806 - 부분합  (0) 2024.12.24