일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 즉시로딩
- TagLibraryValidator
- 동적 계획법
- Today I Learned
- IT 좀 아는 사람
- 최장 공통 부분수열
- @EntityGraph
- 공부 기록
- 지연로딩
- 공부하기 싫어 #그래도 해야해
- 구름톤 트레이닝
- 코딩테스트실력진단
- 금 채굴하기
- 백준 #1010 #다리놓기
- 1005 #ACM craft #백준
- 코드트리 챌린지
- 멀록 조명등
- 코딩테스트
- 1931번
- spring
- 코드트리
- eager
- 완전탐색
- 구름톤
- 구름톤 챌린지
- 행복한 수열의 개수
- 백준
- til
- 회의실 배정
- JPA
- Today
- Total
화분
[9251]LCS 본문
이번 문제는 최장 공통 부분수열(LCS:Longest Common Subsequence)이다. 어떻게 동적계획법을 이용해 풀지 고민하다가 테이블에 어떻게 기록할진 떠올렸으나 코드로 구현할 방법은 떠오르지 않아 결국 인터넷을 참고하였다.
이 문제에 어떻게 접근했냐하면 우선 큰 문제를 해결하기 위한 공통된 작은 문제를 찾아내려 했다. 앞에서부터 공통된 문자를 찾기보단 뒤에서부터 찾으려 했다. 그 결과 다음과 같은 테이블을 완성했다.
A | C | A | Y | K | P | |
C | 3 | |||||
A | 4 | 2 | ||||
P | 1 | |||||
C | 3 | |||||
A | 2 | 2 | ||||
K | 1 |
가장 우측 하단 위치에서부터 왼쪽 행과 윗쪽 열의 안쪽에 있는 수를 증가시켜 나간다. 이렇게 접근하면 LCS를 만족하는 문자의 개수를 알아내는 실마리를 찾은거 같았다. 하지만 문제가 있었다. 어떻게 저 가장 큰 값을 코드로 구현하고 얻어낼 수 있을지가 문제였다. 왼쪽 상단부터 값을 올려나가든 우측 하단부터 값을 올려나가든 재귀함수를 통해 구해야만 할 거 같았다. 이쯤에서 다른 블로그의 풀이 방법을 보기 시작했다.
결과적으로 코드 작성법은 내가 생각했던거와 달랐다. 우선 0번째 행과 0번째 열을 0 값으로 초기화 하고 테이블을 윗쪽부터 차례대로 순회하며 해당위치의 문자열의 값이 같은지 알아낸다. 만약 같다면 북서쪽 칸의 값에 1을 더한다. 만약 다르다면 왼쪽 칸의 값과 윗칸의 값 중 큰 값을 읽어들여 저장한다. 이렇게 하면 O(N1(첫번째 문자열 길이) X N2(두번째 문자열 길이) 의 시간복잡도로 풀 수 있다. 2차원 배열의 테이블을 하나씩 순회하면서 최종적으로 table[N1][N2]의 위치의 값을 얻어내기만 하면 된다.
위의 방법으로 테이블을 만들면 다음과 같은 테이블이 완성된다.
C | A | P | C | A | K | ||
0 | 0 | 0 | 0 | 0 | 0 | 0 | |
A | 0 | 0 | 1 | 1 | 1 | 1 | 1 |
C | 0 | 1 | 1 | 1 | 2 | 2 | 2 |
A | 0 | 1 | 2 | 2 | 2 | 3 | 3 |
Y | 0 | 1 | 2 | 2 | 2 | 3 | 3 |
K | 0 | 1 | 2 | 2 | 2 | 3 | 4 |
P | 0 | 1 | 2 | 3 | 3 | 3 | 4 |
코드는 다음과 같다.
#include <iostream>
#include <algorithm>
using namespace std;
short table[1001][1001];
char a[1002];
char b[1002];
int main(){
short temp = 0;
short strlen1 = 0;
short strlen2 = 0;
//첫번째 문자열 입력 받기
do{
temp += 1;
scanf("%1c", &a[temp]);
strlen1 += 1;
}while(a[temp] != '\n');
temp = 0;
//두번째 문자열 입력 받기
do{
temp += 1;
scanf("%1c", &b[temp]);
strlen2 += 1;
}while(b[temp] != '\n');
//2차원 테이블에 똑같은 문자가 위치한 해당 행렬에 값 표시
for(int i = 0; i < strlen1; i++)
{
for(int j = 0; j < strlen2; j++)
{
if(i == 0 or j == 0)
table[i][j] = 0;
else if(a[i] == b[j])
table[i][j] = table[i-1][j-1] + 1;
else
table[i][j] = max(table[i-1][j], table[i][j-1]);
}
}
cout << table[strlen1-1][strlen2-1] << endl;
}
'Study > CODINGTEST' 카테고리의 다른 글
[구름톤 챌린지 4일차]완벽한 햄버거 만들기 (0) | 2023.08.20 |
---|---|
[구름톤 챌린지 5일차] 이진수 정렬 (0) | 2023.08.19 |
[12865]평범한 배낭 (0) | 2022.02.15 |
[1005]ACM craft (0) | 2022.02.12 |
[1010]다리 놓기 (0) | 2022.02.12 |