Henu
개발냥발
Henu
전체 방문자
오늘
어제
  • 분류 전체보기 (411)
    • DevOps (52)
      • Kubernetes (19)
      • Docker (14)
      • AWS (3)
      • Nginx (4)
      • Linux (4)
      • ArgoCD (1)
      • CN (2)
      • NATS (0)
      • Git (5)
    • Back-End (30)
      • Django (18)
      • Spring (5)
      • JPA (1)
      • MSA (5)
    • CS (87)
      • SystemSoftware (20)
      • OS (25)
      • Computer Architecture (16)
      • Network (23)
      • Database (2)
    • Lang (21)
      • Java (9)
      • Python (4)
      • C# (8)
    • Life (12)
    • 블록체인 (2)
    • Algorithm (204)
      • BOJ (160)
      • 프로그래머스 (19)
      • LeetCode (4)
      • SWEA (1)
      • 알고리즘 문제 해결 전략 (8)
      • DS, algorithms (7)
      • Checkio (5)
    • IT (2)

블로그 메뉴

  • GitHub
  • 글쓰기
  • 관리자

공지사항

  • Free!

인기 글

태그

  • boj
  • BFS
  • 백트래킹
  • 다이나믹 프로그래밍
  • Network
  • DFS
  • docker
  • django
  • 프로그래머스
  • Kubernetes

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Henu

개발냥발

[백준 9252] LCS2 C++
Algorithm/BOJ

[백준 9252] LCS2 C++

2021. 3. 5. 15:22
 

9252번: LCS 2

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

www.acmicpc.net

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

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

입력

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

출력

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

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

예제 입력 1

ACAYKP

CAPCAK

1. 접근 방법

동적 계획법을 통해 특정 범위까지의 값을 구해놓고 다른 범위의 값을 구할 때 이전에 구했던 값을 이용해 빠르게 구한다.

표는 0행 0열부터 시작한다고 가정

first 문자열은 세로 문자열이고, second 문자열은 가로 문자열을 의미

표의 0행과 0열은 문자열을 서로 비교하지 않았을 때를 의미하므로 모두 0을 넣어준다.

dp[7][7]의 일부

현재 두 문자가 같을 때

2행 4열을 보면 숫자 '2'가 있는데 이 의미는 'AC'와 'CAPC'의 LCS 길이를 의미한다. (LCS : 'AC')

first[1] ('C') 와 second[3] ('C') 를 비교하기 전의 LCS 길이는 'A'와 'CAP'까지 비교한 dp[1][3] = 1이다

여기에 서로 동시에 'C'가 추가되었으므로 dp[1][3]에 1을 더해준 값이 'AC'과 'CAPC'의 LCS 길이이다.

현재 두 문자가 다를 때

현재 비교하는 문자가 포함되기 직전의 LCS값 중 큰게 오게된다.

-> dp[3][6]의 값은 'ACA' 와 'CAPCA'의 LCS 길이(3), 'AC' 와 'CAPCAK'의 LCS길이(2) 중 큰 값인 3이 오게된다.

위와 같은 방식으로 표를 추가 해 주면 아래와 같은 표가 완성이 된다.

아래 표에서 우측 하단의 숫자가 LCS길이가 된다.

dp[7][7]

 

LCS값이 최초로 만들어진 곳을 탐색하고, 현재 행과 열이 경계가 되어 이전 숫자가 만들어진 곳을 탐색한다.

이 때 해당 숫자는 각각의 행과 열 중에서 가장 먼저 나타난 것을 찾아간다.

연속적이지 않아도 되기 때문에 서로다른 LCS 문자열이 나타날 수 있다

LCS 문자열 구하기

<code>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <cstring>
 
using namespace std;
 
string first, second, LCS = "";
int dp[1001][1001];
 
void findLCS(){
    // dp 배열을 모두 0으로 초기화
    memset(dp, 0, sizeof(dp));
    
    // LCS표를 구하는 과정
    for(int row = 1; row <= first.size(); row++){
        for(int col = 1; col <= second.size(); col++){
            if(first[row-1] == second[col-1]){
                // 만약 같은 문자가 나오면 두 문자열에서 
                // 해당 두 문자를 비교하기 전의 LCS의 길이에 1을 더한다
                dp[row][col] = dp[row-1][col-1] + 1;
            }
            // 문자가 다르다면 first[row-1]까지의 문자열 + second[col] 까지의 문자열 간의 LCS값과
            // first[row]까지의 문자열 + second[col+1] 까지의 문자열 간의 LCS값 중 큰값을 저장
            else dp[row][col] = max(dp[row-1][col], dp[row][col-1]);
        }
    }
    cout << dp[first.size()][second.size()] << "\n";
    
    int f_idx = second.size();
    for(int row = first.size(); row >= 1; row--){
        for(int col = f_idx; col >= 1; col--){
            if(dp[row][col] == dp[row-1][col]){
                // 바로 위 dp값이 같으면 현재 열 값을 유지한다
                f_idx = col;
                break;
            }
            else if(dp[row][col] == dp[row][col-1]) continue;
            else{
                LCS = first[row-1] + LCS;
            }
        }
    }
    cout << LCS;
}
 
int main(){
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    cin >> first >> second;
    findLCS();
    return 0;
}
 
Colored by Color Scripter
cs

2021 02 05

4ms

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

[백준 10830] 행렬 제곱 C++  (0) 2021.03.10
[백준14500] 테트로미노 C++  (0) 2021.03.07
[백준 1535] 안녕 C++  (0) 2021.02.26
[백준 12865] 평범한 배낭 C++  (0) 2021.02.26
[BOJ] 프린터 큐_1966.c++  (0) 2020.09.07
    'Algorithm/BOJ' 카테고리의 다른 글
    • [백준 10830] 행렬 제곱 C++
    • [백준14500] 테트로미노 C++
    • [백준 1535] 안녕 C++
    • [백준 12865] 평범한 배낭 C++

    티스토리툴바