[Java] 백준 9251번: LCS

U·2025년 3월 27일

백준

목록 보기
101/116

[문제 바로 가기] - LCS

📌 유형 : dp

이 문제는 LCS(Longest Common Subsequence), 즉 최장 공통 부분 수열 문제로 개념은 여기에서 이해했다.

💡 아이디어

ACAYKP
CAPCAK

LCS는 두 수열이 주어졌을 때 가장 긴 공통 부분 수열을 구하면 되는데 이 문제에서는 위와 같이 문자열로 주어졌다.

예제를 바탕으로 문자열 s1s2를 비교해보는 표를 작성했다. s1를 기준으로 문자 하나씩 비교해보도록 하겠다.

1. A와 CAPCAK 비교

ACAYKP
C0
A1
P1
C1
A1
K1

여기서 두번째 A가 나왔을 때 2가 되는거 아닌가 했지만 A와 비교했을 때 두번째 A도 길이가 1이 될 수 밖에 없다. CAPCAK의 [A]와 ACAYKP의 [A]를 비교하는 것이기 때문에!

2. AC와 CAPCAK 비교

ACAYKP
C01
A11
P11
C12
A12
K12

ACAYKP의 [A, C]와 CAPCAK의 [A, C]가 일치하기 때문에 두번째 C에서 +1을 한다.

3. ACA와 CAPCAK 비교

ACAYKP
C011
A112
P112
C122
A123
K123

ACAYKP의 [A, C, A]와 CAPCAK의 [A, C, A]가 일치하기 때문에 두번째 A에서 +1을 한다.

4. ACAYK와 CAPCAK 비교

ACAYKP
C01111
A11222
P11222
C12222
A12333
K12334

ACAY는 ACA와 큰 차이가 없어 생략했다.
ACAYKP의 [A, C, A, K]와 CAPCAK의 [A, C, A, K]가 일치하기 때문에 K에서 +1을 한다.

5. ACAYKP와 CAPCAK 비교

ACAYKP
C011111
A112222
P112223
C122223
A123333
K123344

표를 다 채우면 위와 같다.

규칙을 찾아보면 s1의 문자와 s2의 문자가 같을 때 (행의 인덱스 - 1)(열의 인덱스 - 1)의 값에 +1을 하고, 같지 않을 경우엔 (행의 인덱스 - 1) 또는 (열의 인덱스 - 1) 중 큰 값을 선택한다.

즉, 2차원 dp 배열을 사용하여 가장 긴 공통 부분 수열을 저장해가면 되는 것이다.

	for (int i = 1; i <= len1; i++) {
		for (int j = 1; j <= len2; j++) {
			if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
				dp[i][j] = dp[i - 1][j - 1] + 1;
			} else {
				dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]);
			}
		}
	}

풀이

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * 백준 9251번 LCS
 * - dp
 */

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String s1 = br.readLine();
		String s2 = br.readLine();
		
		int len1 = s1.length();
		int len2 = s2.length();
		int[][] dp = new int[len1 + 1][len2 + 1];
		
		for (int i = 1; i <= len1; i++) {
			for (int j = 1; j <= len2; j++) {
				if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
					dp[i][j] = dp[i - 1][j - 1] + 1;
				} else {
					dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]);
				}
			}
		}

		System.out.println(dp[len1][len2]);
	}
}
profile
백엔드 개발자 연습생

0개의 댓글