PS❯BOJ2021-09-293 min read
[BOJ 9252] LCS 2 - Java (최장 공통 부분 수열 & DP 테이블 역추적)
2차원 DP 테이블로 두 문자열의 최장 공통 부분 수열(LCS) 길이를 구한 뒤, (len1, len2)에서 역방향으로 대각선 전이를 추적하여 실제 LCS 문자열을 복원하는 풀이
#BOJ#DP#LCS#문자열#역추적#Java
1. 문제 개요 및 조건 분석
| 항목 | 내용 |
|---|---|
| 문제 이름 | LCS 2 (백준 9252번 / 골드 4) |
| 플랫폼 / 난이도 | 백준 (골드 4, 9252번) |
| 문제 링크 | 백준 9252번 |
| 제한 사항 | 시간 제한 0.4초, 메모리 제한 256MB |
| 입력 조건 | 두 문자열 (최대 1,000글자) |
| 핵심 규칙 | 두 문자열의 최장 공통 부분 수열(LCS)의 길이와 실제 문자열을 모두 출력 |
2. 접근 아이디어: 2차원 DP & 역추적(Backtracking)
LCS 2차원 점화식
- $s_1[i-1] == s_2[j-1]$이면: $dp[i][j] = dp[i-1][j-1] + 1$
- 다르면: $dp[i][j] = \max(dp[i-1][j], dp[i][j-1])$
실제 문자열 역추적
- $(len_1, len_2)$ 위치부터 시작하여:
- $s_1[i-1] == s_2[j-1]$이면: 공통 문자를 스택에 넣고 $(i-1, j-1)$로 대각선 이동.
- 다르면: $dp[i-1][j]$와 $dp[i][j-1]$ 중 더 큰 값을 가진 쪽으로 이동.
- 스택에서 꺼내며 문자열을 복원합니다.
3. Java 풀이 코드
import java.io.*;
import java.util.*;
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 n = s1.length();
int m = s2.length();
int[][] dp = new int[n + 1][m + 1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; 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 - 1][j], dp[i][j - 1]);
}
}
}
int lcsLen = dp[n][m];
System.out.println(lcsLen);
if (lcsLen == 0) return;
// 역추적으로 실제 문자열 복원
StringBuilder sb = new StringBuilder();
int i = n, j = m;
while (i > 0 && j > 0) {
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
sb.append(s1.charAt(i - 1));
i--;
j--;
} else if (dp[i - 1][j] >= dp[i][j - 1]) {
i--;
} else {
j--;
}
}
System.out.println(sb.reverse().toString());
}
}
4. 복잡도 분석
- 시간 복잡도: $O(N \times M)$ — $1,000 \times 1,000 = 10^6$ 연산으로 0.1초 이내 완료.
- 공간 복잡도: $O(N \times M)$ — $1001 \times 1001$ 정수 DP 테이블.
5. 채점 결과 및 통과 인증

← PREVIOUS LOG
[BOJ 1005] ACM Craft - Java (위상 정렬 Topological Sort & DAG DP)
NEXT LOG →[BOJ 2533] 사회망 서비스(SNS) - Java (트리 DP & 최소 얼리어답터)
COMMENTS // GITHUB DISCUSSIONS (GISCUS)