본문 바로가기

Coding/백준

9251번 LCS

 다이나믹 프로그래밍.

 

 예시로 나온 ACAYKP, CAPCAK으로 설명해보자. 첫번째 문자열 시작점을 기준으로 하나씩 비교해서 LCS 길이를 구하게 되면 시간을 초과하게 된다. (이중 for문) 

 

 따라서 DP로 해결하면 된다.

  A C A Y K P
C 0          
A 1          
P 1          
C 1          
A 1          
K 1          

 

A를 기준으로 생각해보자.

 1. C를 만났을때 같지 않으므로 0

 2. A를 만났을때 같으므로 1

 3. P를 만났을때 같지 않으므로 0이지만 그 전에 A를 만났으므로 최대값 1

 4. C를 만났을때도 마찬가지 1

 5. A를 만났을때 같으므로 1

 6. K를 만났을때 최대값 1

 

  A C A Y K P
C 0 1        
A 1 1        
P 1 1        
C 1 2        
A 1 2        
K 1 2        

C를 기준으로 생각해보자.

 1. C를 만났을때 같으므로 1

 2. A를 만났을때 같지 않으므로 최대값 1

 3. P를 만났을때 같지 않으므로 최대값 1

 4. C를 만났을때 같으므로 그 전을 기준으로 생각해야된다. 무슨 말이냐? A-P와 C-C쪽(빨간 숫자)를 보면 C-C가 만나기 직전에 A-P에서 1이라는 숫자가 적혀있다. 이것은 A-A에서 쭉 내려온 숫자다. 이 말은 A-P까지 'AA'라는 LCS가 있었다는 것이고 C-C를 만났을때 이 경우를 생각해서 +1을 해주는 것이다. 즉, 'AC'라는 LCS가 완성되어 2가 된다.

 5. A를 만났을때 같지 않으므로 최대값 2

    (우리는 현재 최대값을 찾는 것이기 때문에 C-A가 만나기 전 즉 A-A와 C-C(파란 글자)를 비교해 최대값을 넣어주면 된다.)

 6. K를 만났을때 같지 않으므로 최대값 2

 

 이렇게 반복해주면

  A C A Y K P
C 0 1 1 1 1 1
A 1 1 2 2 2 2
P 1 1 2 2 2 3
C 1 2 2 2 2 3
A 1 2 3 3 3 3
K 1 2 3 3 4 4

완성이 된다.

 

ps. 설명이 좀 어렵게 됐는데 실제로 테이블을 그려서 하나씩 계산해보면 이해하기 쉽다.

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
#include <iostream>
#include <algorithm>
#define MAX 1001
 
using namespace std;
 
string str1;
string str2;
int dp[MAX][MAX];
 
void solved(){
    unsigned long size1=str1.size();
    unsigned long size2=str2.size();
    
    for(int i=1;i<=size1;i++){
        for(int j=1;j<=size2;j++){
            if(str1[i-1]==str2[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[size1][size2];
    
}
 
int main(){
    
    cin >> str1 >> str2;
    
    solved();
}
cs

'Coding > 백준' 카테고리의 다른 글

1766번 문제집  (0) 2021.03.03
2252번 줄 세우기  (0) 2021.03.02
1541번 잃어버린 괄호  (0) 2021.02.05
2798번 블랙잭  (0) 2021.01.20
6603번 로또  (0) 2021.01.20