https://www.acmicpc.net/problem/6597
6597번: 트리 복구
창영이는 바이너리 트리를 매우 좋아한다. 그가 가장 좋아하는 게임은 바이너리 트리를 만들고, 노드에 알파벳 대문자를 하나씩 쓰는 것이다. 같은 알파벳을 여러 노드에 쓰지 않는다. 아래는
www.acmicpc.net
전위 순회에서 루트 노드는 맨 앞, 즉 0번째 인덱스에 존재하고, 중위 순회에서 왼쪽 서브 트리와 오른쪽 서브 트리는 루트 노드를 중심으로 나뉘어져 있다. 즉 전위 순회에서 얻은 루트 노드를 중위 순회에서 찾을 수 있다면 왼쪽 서브 트리와 오른쪽 서브 트리의 길이를 얻을 수 있고, 이를 이용하면 전위 순회에서 왼쪽 서브 트리와 오른쪽 서브 트리를 찾을 수 있다. 루트 노드와 왼쪽 서브 트리, 오른쪽 서브 트리를 모두 알고 있다면 이를 왼쪽 서브 트리, 오른쪽 서브 트리, 루트 노드 순으로 출력해 후위 순회를 만들 수 있으므로 재귀를 이용해 전위 순회와 중위 순회를 후위 순회로 바꿀 수 있다.
#include <cstdio>
#define MAX_LEN 26
// pre, in: 트리의 전위 및 중위 순회
char pre[MAX_LEN], in[MAX_LEN];
// pre_idx[i], in_idx[i]: 트리의 전위 및 중위 순회에서 i + 'A'의 인덱스
int pre_idx[MAX_LEN], in_idx[MAX_LEN];
// 전위 순회의 [ps, pe), 중위 순회의 [is, ie) 구간을 후위 순회로 복구
void dfs(int ps, int pe, int is, int ie) {
// im: 중위 순회에서 루트 노드(pre[ps])의 인덱스
// prs: 전위 순회에서 오른쪽 서브 트리의 루트 노드의 인덱스
// 즉, 전위 순회의 시작 지점(ps에서 왼쪽 서브 트리의 길이im - is)와
// 루트 노드의 길이(1)를 더한 값
int im = in_idx[pre[ps] - 'A'], prs = ps + (im - is) + 1;
// pe - ps가 1보다 클 경우, 즉 트리가 자식 노드를 가진 트리일 경우
if (pe - ps > 1) {
// 왼쪽 서브 트리와 오른쪽 서브 트리를 차례로 후위 순회로 바꾼 뒤
dfs(ps + 1, prs, is, im);
dfs(prs, pe, im + 1, ie);
}
// pe - ps가 true일 경우, 즉 트리의 루트 노드가 존재할 경우 이를 출력
if (pe - ps) printf("%c", pre[ps]);
}
int main() {
// 각 트리의 길이
int len;
// 각 테스트 케이스를 입력받은 뒤
while (scanf("%s %s", pre, in) != EOF) {
// 두 순회에서 각 노드의 인덱스를 배열에 저장하고
for (len = 0; len < MAX_LEN && in[len]; len++){
pre_idx[pre[len] - 'A'] = len;
in_idx[in[len] - 'A'] = len;
}
// dfs를 이용해 후위 순회를 출력
dfs(0, len, 0, len);
// 개행 문자를 출력해 테스트 케이스의 출력을 종료
printf("\n");
}
return 0;
}
'알고리즘 > 문제 풀이' 카테고리의 다른 글
백준 17471번: 게리맨더링 (0) | 2022.05.07 |
---|---|
백준 20005번: 보스몬스터 전리품 (0) | 2022.05.06 |
백준 19953번: 영재의 산책 (0) | 2022.05.04 |
백준 14676번: 영우는 사기꾼? (0) | 2022.04.13 |
백준 2201번: 이친수 찾기 (0) | 2022.04.13 |