https://www.acmicpc.net/problem/9251
9251번: LCS
LCS(Longest Common Subsequence, 최장 공통 부분 수열)문제는 두 수열이 주어졌을 때, 모두의 부분 수열이 되는 수열 중 가장 긴 것을 찾는 문제이다. 예를 들어, ACAYKP와 CAPCAK의 LCS는 ACAK가 된다.
www.acmicpc.net
EXPLANATION
LCS(Longest Common Subsequence, 최장 공통 부분 수열)
이 문제를 푸는 코드는 직관적으로 이해하기 쉽다.
첫번째 문자열에서 i번째 문자를 a[i]라 하고
두번째 문자열에서 j번째 문자를 b[j]라 하자.
첫번째 문자열에서 i번째까지와,
두번째 문자열에서 j번째까지를
비교했을 때 구해지는 LCS의 길이를 dp[i][j]라 하자.
a[i]와 b[j]가 같을 때,
dp[i][j] = dp[ i-1 ][ j-1 ] + 1이다.
a[i]와 b[j]가 다를 때,
dp[i][j] = max( dp[i][j-1], dp[i-1][j] )이다.
예제와 함께 살펴 보자
A C A Y K P
C A P C A K
ex)
dp[4][5]를 구해보자.
a[4] == b[5]
=> dp[4][5] = dp[3][4] + 1
= 3 + 1 = 4
A C A Y K P
C A P C A K
dp[5][5]를 구해보자.
a[5] != b[5]
=> dp[5]dp[5] = max(dp[5][4], dp[4][5]) = max(3, 4)
= 4
A C A Y K P
C A P C A K
A C A Y K P
C A P C A K
i나 j 둘 중에 하나가 0이면 위의 규칙을 따를 때 음의 index가 발생한다.
따라서 여기서 base를 나타내야 한다.
dp[0][j] = dp[0][j] = 0
한 문자열에서 0번째까지와
나머지 다른 문자열에서 i 또는 j번째까지를 비교했을 때
구해지는 LCS의 길이는 당연히 0이다.
한 문자열에서 비교 가능한 문자가 애초에 존재하지 않으므로.
점화식
dp[i][0] = dp[0][j] = 0
if (a[i-1] == b[j-1]) dp[i][j] = dp[i-1][j-1] + 1;
else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
CODE
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int MAX = 1001; //for[0,string.length()]
int dp[MAX][MAX]; //0으로 초기화 됨. 자동으로 base 설정: dp[i][0] = dp[j][0] = 0, string의 index는 0부터 시작.
int main(){
string a, b;
cin >> a >> b;
int a_size = a.length();
int b_size = b.length();
for (int i = 1; i <= a_size; i++) //base: dp[i][0]= dp[0][j] = 0. 제외하고 i=1, j=1부터
for (int j = 1; j <= b_size; j++){
if (a[i-1] == b[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[a_size][b_size] << "\n";
return 0;
}

'백준BOJ > 동적 계획법' 카테고리의 다른 글
| 백준 11066 파일 합치기 (0) | 2022.06.25 |
|---|---|
| 백준 12865 평범한 배낭 (0) | 2022.06.13 |
| 백준 11054 가장 긴 바이토닉 부분 수열 (0) | 2022.06.12 |
| 백준 11053 가장 긴 증가하는 부분 수열 (0) | 2022.06.11 |
| 백준 2156 포도주 시식 (0) | 2022.06.11 |
댓글