알고리즘

[BOJ] LCS - 9251

2023. 6. 20. 15:40
목차
  1. 🎨 문제
  2. 📘 풀이
  3. 📗 코드

🎨 문제

 

9251번: LCS

LCS(Longest Common Subsequence, 최장 공통 부분 수열)문제는 두 수열이 주어졌을 때, 모두의 부분 수열이 되는 수열 중 가장 긴 것을 찾는 문제이다. 예를 들어, ACAYKP와 CAPCAK의 LCS는 ACAK가 된다.

www.acmicpc.net

📘 풀이

이 문제는 DP로 풀 수 있습니다. 우선 LCS(Longest Common Subsequence)를 예시로 이해해봅시다. 

 

우선 두 문자열이 주어집니다. (더 많을 수도 있지만 문제에서는 2개가 주어집니다.)

  • ACAYKP
  • CAPCAK

서브 시퀀스는 주어진 문자열에서 순서를 바꾸지 않고 몇 개의 글자를 뺀 것을 말합니다. 첫 번째 문자열의 경우 ACA, AKP, C 등이 서브 시퀀스가 됩니다. 

 

LCS는 구할 수 있는 모든 서브 시퀀스 중 서로 같은 가장 긴 서브 시퀀스를 의미합니다. 예시의 경우 ACAK가 LCS가 됩니다.

 

LCS를 구하기 위해 모든 서브 시퀀스를 구하고 비교한다면 한 문자열의 서브 시퀀스를 구하는데 오랜 시간이 걸립니다. 하지만 DP를 사용하면 두 문자열의 길이의 곱의 시간으로 LCS를 구할 수 있습니다.

 

길이가 A, B인 문자열이 있을 때 이 두 문자열의 LCS의 길이를 LCS(A, B)라 합시다. 이때 LCS(A, B)는 다음을 만족합니다.

  • str1[A] == str2[B] 라면 str1[A]로 끝나는 LCS가 존재한다. 즉, LCS(A, B) = LCS(A -1, B - 1) + 1 을 만족합니다.
  • 만약 그렇지 않다면, LCS(A, B) = max(LCS(A - 1, B), LCS(A, B - 1))이 됩니다.

여기에 메모리제이션을 적용해줍니다.

private static int LCS(int x, int y) {

    if (x < 0 || y < 0) return 0;

    if (DP[x][y] != -1) return DP[x][y];

    if (str1[x] == str2[y]) {
        return DP[x][y] = LCS(x - 1, y - 1) + 1;
    }

    return DP[x][y] = Math.max(LCS(x - 1, y), LCS(x, y -1));
}

📗 코드

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

import static java.lang.System.in;

public class Main {

    static int[][] DP;
    static char[] str1, str2;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        str1 = br.readLine().toCharArray();
        str2 = br.readLine().toCharArray();
        DP = new int[1004][1004];
        for (int i = 0; i < 1004; i++) {
            Arrays.fill(DP[i], -1);
        }
        System.out.println(LCS(str1.length - 1, str2.length - 1));
    }

    private static int LCS(int x, int y) {

        if (x < 0 || y < 0) return 0;

        if (DP[x][y] != -1) return DP[x][y];

        if (str1[x] == str2[y]) {
            return DP[x][y] = LCS(x - 1, y - 1) + 1;
        }

        return DP[x][y] = Math.max(LCS(x - 1, y), LCS(x, y -1));
    }
}
저작자표시 (새창열림)

'알고리즘' 카테고리의 다른 글

[BOJ] 토마토 - 7569  (0) 2023.06.19
[BOJ] 토마토 - 7576  (0) 2023.06.16
[BOJ] 팰린드롬?  (0) 2023.06.09
[BOJ] 경로 찾기 - 1513  (0) 2023.06.08
[BOJ] 사탕 가게 - 4781  (0) 2023.06.05
  1. 🎨 문제
  2. 📘 풀이
  3. 📗 코드
'알고리즘' 카테고리의 다른 글
  • [BOJ] 토마토 - 7569
  • [BOJ] 토마토 - 7576
  • [BOJ] 팰린드롬?
  • [BOJ] 경로 찾기 - 1513
acisliver
acisliver
acisliver
와당탕탕 개발놀이터
acisliver
전체
오늘
어제
  • 분류 전체보기 (65)
    • 회고 (11)
    • Spring (3)
    • 알고리즘 (21)
    • Java (2)
    • DevOps (2)
    • Shell (2)
    • Nginx (1)
    • Database (22)
    • Project (1)

블로그 메뉴

  • 태그
  • 방명록
  • GitHub
  • Notion

공지사항

인기 글

태그

  • 풀스택
  • 백준
  • 카카오
  • 오픈소스 컨트리뷰톤
  • 오픈소스
  • 코딩테스트
  • FuntionalInterface
  • 자바
  • 풀 테이블 스캔
  • 이진탐색
  • 인덱스
  • 풀 인덱스 스캔
  • 구름톤 트레이닝
  • binarySearch
  • Spring
  • 이분탐색
  • mysql
  • 알고리즘
  • 프로그래머스
  • Leetcode
  • spring boot
  • 프리코스
  • Java
  • FOSSLight
  • dp
  • 우아한테크코스
  • DevOps
  • Bash
  • Shell
  • innodb

최근 댓글

최근 글

hELLO · Designed By 정상우.
acisliver
[BOJ] LCS - 9251
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.