https://www.acmicpc.net/problem/9251
9251번: LCS
LCS(Longest Common Subsequence, 최장 공통 부분 수열)문제는 두 수열이 주어졌을 때, 모두의 부분 수열이 되는 수열 중 가장 긴 것을 찾는 문제이다. 예를 들어, ACAYKP와 CAPCAK의 LCS는 ACAK가 된다.
www.acmicpc.net
문제
LCS(Longest Common Subsequence, 최장 공통 부분 수열)문제는 두 수열이 주어졌을 때, 모두의 부분 수열이 되는 수열 중 가장 긴 것을 찾는 문제이다.
예를 들어, ACAYKP와 CAPCAK의 LCS는 ACAK가 된다.
입력
첫째 줄과 둘째 줄에 두 문자열이 주어진다. 문자열은 알파벳 대문자로만 이루어져 있으며, 최대 1000글자로 이루어져 있다.
출력
첫째 줄에 입력으로 주어진 두 문자열의 LCS의 길이를 출력한다.
풀이
풀이를 상세히 적기가 난해하다..
1. 핵심은 결국 이것도 DP라는 점이다. 3가지 포인트를 생각해보자.
첫째로, 큰 문제를 작은 문제로 분할해야한다. 'ACAYKP'와 'CAPCAK'의 LCS를 구하는 것은 'ACAYK'와 'CAPCA'의 LCS를 알면 구할 수 있다. (길이 5일 때의 LCS에다가 마지막 알파벳을 비교해서 같으면 1을 더해주면 된다)
두번째, 이 작은 문제들로 큰 문제를 해결할 수 있다. (앞서 언급한 것과 같다)
세번째, 이 작은 문제들이 반복해서 필요하다! 즉, 길이 2일때의 값을 알아야 3일 때를, 그 값으로 4일때, 5일때 최종적으로 6일 때 값을 구할 수 있다. 길이 6일 때의 LCS를 구하기 위해선 길이 2, 3 일 떄의 LCS 값이 반복적으로 필요하므로
이는 DP를 사용할 수 있다!!
그래서 결국 점화식을 생각해보면,
1) 새로 추가되는 알파벳이 서로 같을 경우!:
DP[i][j] = DP[i - 1][j - 1] + 1 이다. 'ACAYK', 'CAPCA'의 LCS는 'ACA'로 3이다. 이 때 만약 각각 'P'가 추가된다면
'ACAYKP' 와 'CAPCAP'의 LCS는 'ACAP'로 4가 된다.
2) 새로 추가되는 알파벳이 서로 다른 경우:
이어서, 각각 'P', 'K'가 추가되는 경우라면 'ACAYKP' 와 'CAPCAK'의 LCS는 'ACAK'로 4가 된다. 이는, 'ACAYKP'와 추가되지 않은 'CAPCA'를 비교했을 때는 LCS가 'ACA'로 3이지만, 'ACAYK' (길이5) 와 'CAPCAK'(길이6) 을 비교하면, 'ACAK'로 4가 된다. 즉, 추가되는 알파벳이 다르다면, 당연하게도 한 쪽만 추가 됐을 때의 경우 2가지 중 큰 값과 동일하게 된다.
DP[i][j] = max(DP[i][j - 1], DP[i - 1][j]) 이다.
코드
import sys
# 공백을 추가해주어, string[0] = ' ' 이 되게 만들었다.
first_string = ' ' + sys.stdin.readline().strip()
second_string = ' ' + sys.stdin.readline().strip()
# 각 string의 길이를 저장해주고
first_len = len(first_string)
second_len = len(second_string)
# string의 길이만큼 2차원 배열을 만들었다. 이는 각 string의 길이일 때, LCS를 저장해두는 memo이다.
memo_table = [[0] * (second_len) for _ in range(first_len)]
# memo_table[i][j]는 새롭게 추가된 string이 같으면, memo[i - 1][j - 1] + 1과 같다. 그렇지 않다면, first_string이 한 개 짧을 때와 second_stirng이 한 개 짧을 때 중 큰 값을 가진다.
for i in range(1, first_len):
first_new_str = first_string[i]
for j in range(1, second_len):
second_new_str = second_string[j]
if first_new_str == second_new_str:
memo_table[i][j] = memo_table[i - 1][j - 1] + 1
else:
memo_table[i][j] = max(memo_table[i][j - 1], memo_table[i - 1][j])
print(memo_table[first_len - 1][second_len - 1])
'프로그래밍 > JUNGLE' 카테고리의 다른 글
[BOJ]12865. 평범한 배낭 (python) (0) | 2021.08.27 |
---|---|
[BOJ]1931. 회의실배정 (python) (0) | 2021.08.27 |
[컴퓨터시스템] 1.8 ~ 1.10 (0) | 2021.08.25 |
그래프 탐색 기본 (DFS / BFS) (0) | 2021.08.19 |
WEEK00. 정글을 시작하며 [SW사관학교 정글] (2) | 2021.08.08 |