-
[백준]9251: LCS(java)Algorithm/백준 2022. 3. 23. 21:53728x90
https://www.acmicpc.net/problem/9251
문제
LCS(Longest Common Subsequence, 최장 공통 부분 수열)문제는 두 수열이 주어졌을 때, 모두의 부분 수열이 되는 수열 중 가장 긴 것을 찾는 문제이다.
예를 들어, ACAYKP와 CAPCAK의 LCS는 ACAK가 된다.
입력
첫째 줄과 둘째 줄에 두 문자열이 주어진다. 문자열은 알파벳 대문자로만 이루어져 있으며, 최대 1000글자로 이루어져 있다.
출력
첫째 줄에 입력으로 주어진 두 문자열의 LCS의 길이를 출력한다.
예제 입력 1
ACAYKP CAPCAK
예제 출력 1
4
풀이
dp문제이다. dp배열을 담는 과정은 다음과 같이 생각할 수 있다.
자가 현재 서로 같은가? 같다면 +1을 해줘야한다.
처음 C가 같은 순간이다.
이 이후 왜 A, Y, K, P는 C와 다르지만 왜 1이 될까? 는 위 그림을 참고하면 쉽게 이해할 수 있다.
우린 가장 긴 부분 수열을 찾기 때문에 이미 C와 같은 순간 그 뒤에는 모두 일치하지 않아도 답은 1이 되기때문이다.
조금 더 쉽게 단어가 ACAYKP / C 라고 생각하면 쉽게 이해할 수 있다.
위 과정은 다음과 같은 코드로 해결할 수 있다.
이경우도 위의 경우와 같다. A와 같은 순간 A 외의 문자는 같지 않아도 반드시 1이상을 가져야한다.
단어 A / CAPCAK 인 경우로 이해하면 쉽게 이해할 수 있다.
여기서 의문 만약 이미 같은 단어가 나온 후 같은 단어를 찾으면 어떻게 처리해줘야할까? 정답은 아래와 같다.
여기서 우리는 이미 C가 같았고 그 후에 A가 또 같은 경우를 만나게 된다.
위 과정을 반복하면 아래와 같다.
위 과정을 반복하는 코드는 아래와 같다.
for(int i=1; i<=N; i++) { for(int j=1; j<=M; j++) { if(str1.charAt(j-1) == str2.charAt(i-1)) { dp[i][j] = dp[i-1][j-1] + 1; } else { dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]); } } }
전체 코드
import java.io.BufferedReader; import java.io.InputStreamReader; public class bJ_G5_9251_LCS { public static void main(String[] args) throws Exception{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str1 = br.readLine(); String str2 = br.readLine(); int M = str1.length(); int N = str2.length(); int[][]dp = new int[N+1][M+1]; for(int i=1; i<=N; i++) { for(int j=1; j<=M; j++) { if(str1.charAt(j-1) == str2.charAt(i-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.printf("%d", dp[N][M]); } }
728x90'Algorithm > 백준' 카테고리의 다른 글
[백준]1039: 교환(java) (0) 2022.03.26 [백준]17135: 캐슬 디펜스 (0) 2022.03.25 [백준]12865: 평범한 배낭 (0) 2022.03.24 [백준]14500: 테트로미노(java) (0) 2022.03.22 [백준]2866: 문자열 잘라내기(java) (0) 2022.03.21