
DP 방식으로 생각해보자~
DP 문제를 풀 때는,
이렇게 풀어야 한다!
두 수열이 있으니, 당연히 두 수열을 모두 살펴봐야한다.
각 수열의 각 문자 하나씩 생각해주어야 하는데, 그렇다면 당연히 2차원 배열로 정의해야 한다.
그래서 DP[i][j]의 형태가 된다.
각 수열을 A와 B라고 했을 때, DP[i][j]는 수열 A를 i까지 살펴봤을 때, 수열 B를 j까지 살펴봤을 때의 최장 길이라고 할 수 있다!
하나씩 생각해보다 보면 규칙을 찾을 수 있을 것이다!
각 수열의 문자를 모두 확인해봐야하니 2중 for문으로 풀어야 한다.
그럼 첫 번째 수열의 첫 번째 문자 A와 두 번째 수열을 비교해보자.
↓
ACAYKP
CAPCAK
DP 배열은 이렇게 됐을 것이다.
| C | A | P | C | A | K | ||
|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
| A | 0 | 0 | 1 | 1 | 1 | 1 | 1 |
| C | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| A | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Y | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| K | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| P | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
여기까지는 별다른 규칙이 없다.
첫 번째 수열의 두 번째 문자 C와 두 번째 수열을 비교해보자
↓
ACAYKP
CAPCAK
AC를,AC를 찾을 수 있으니 2가 되는 것이 당연하다.2가 될 수 있었던 이유는, 그 전에 1이 있었다는 것인데 그 1은 어떤 값을 가져온 걸까?DP[i][j] = DP[i-1][j-1] + 1이 된다!이까지 살펴보면 규칙을 다 찾은 것이다!
2중 for 문을 통해서 두 수열을 모두 비교하고,
DP[i][j] = DP[i-1][j-1] + 1DP[i][j] = max(DP[i][j-1], DP[i-1][j]A, 두 번째 수열에서는 C를 살펴보고 있는 상황을 생각해보자. ↓
ACAYKP
CAPCAK
↑
DP 배열을 마저 완성하면 이렇게 된다.

import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 수열 입력 받기
char[] seriesA = br.readLine().toCharArray();
char[] seriesB = br.readLine().toCharArray();
// DP
int lA = seriesA.length;
int lB = seriesB.length;
int[][] dp = new int[lA + 1][lB + 1]; // 길이만 구하면 되기에 값만 저장하면 된다
for (int i = 1; i <= lA; i++) {
for (int j = 1; j <= lB; j++) {
// 두 수열의 직전 인덱스까지의 최대 길이 + 1
if (seriesA[i - 1] == seriesB[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]);
}
}
// 출력
System.out.println(dp[lA][lB]);
}
}