: solved.ac class 2 - silver 4

https://www.acmicpc.net/problem/4949

 

4949번: 균형잡힌 세상

하나 또는 여러줄에 걸쳐서 문자열이 주어진다. 각 문자열은 영문 알파벳, 공백, 소괄호("( )") 대괄호("[ ]")등으로 이루어져 있으며, 길이는 100글자보다 작거나 같다. 입력의 종료조건으로 맨 마

www.acmicpc.net

 

+ 힌트 : 7번째의 " ."와 같이 괄호가 하나도 없는 경우도 균형잡힌 문자열로 간주할 수 있다.

 

 

예제 입력

So when I die (the [first] I will see in (heaven) is a score list).
[ first in ] ( first out ).
Half Moon tonight (At least it is better than no Moon at all].
A rope may form )( a trail in a maze.
Help( I[m being held prisoner in a fortune cookie factory)].
([ (([( [ ] ) ( ) (( ))] )) ]).
 .
.

 

예제 출력

yes
yes
no
no
no
yes
yes

 

정답

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#define SIZE 101


int main() {

	char stnc[SIZE], stack[SIZE];

	while (1) {
		gets(stnc);
		if (stnc[0] == '.') break;

		int top = -1;

		for (int i = 0; stnc[i] != '.'; i++) {

			if (stnc[i] == '(' || stnc[i] == '[')
				stack[++top] = stnc[i];

			else if (stnc[i] == ')')
				if (top > -1 && stack[top] == '(') --top;
				else {top = -2; break;}

			else if (stnc[i] == ']')
				if (top > -1 && stack[top] == '[') --top;
				else { top = -2; break; }
		}

		puts(top == -1 ? "yes" : "no");
	}

	return 0;
}


해설

 

  • 스택을 이용한다.
  • -> 여는괄호 (, [ 가 들어오면 스택에 push하여 담고, 그에 상응하는 닫는괄호 ), ] 와 만나면 pop되게 한다.
  • -> 괄호들이 짝을 맞추어 만나지 못한 경우 ex) ( [ ) ] 스택 안에는 괄호들이 그대로 남아 있을 것이다.
  • -> 반복문을 통해 문장이 끝날 때까지 위 절차를 반복한다.
  • -> 문장이 끝나면 스택의 top을 검사한다.
  • 괄호들이 올바른 짝을 만나 pop되었다면 스택이 비어 top은 초기값으로 돌아와 있을 것이고, 아니라면 다른 값이 되어 있을 것이다. 전자의 경우 yes, 후자의 경우 no를 출력한다.

+ 여는괄호 없이 닫는괄호가 먼저 입력된 경우 반복문을 중단하고 무조건 no를 출력하도록 한다.

 

 

 

1. 배열의 최대 크기를 매크로 상수로 선언해 준다. 문자열 최대 길이인 100글자에 널 문자를 더한 101이다.

문자열을 넣어줄 stnc 배열과 스택으로 사용할 배열을 각각 최대 크기로 선언한다.

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#define SIZE 101


int main() {

	char stnc[SIZE], stack[SIZE];
	//입력받은 문자열을 넣어줄 배열과 스택으로 사용할 배열

 

2. 문자열을 하나씩 입력받는다. 스택의 top도 미리 -1로 초기화시켜 둔다.

	while (1) {
		gets(stnc); //문자열 입력
		if (stnc[0] == '.') break; // 입력의 끝 인식

		int top = -1; //스택의 top

+ 의외로 이 부분에서 상당히 헤맸다. " ." (공백이 하나 들어오고 온점이 들어오는 경우) 와 "."(온점만 들어오는 경우)를 잘 구분해야 한다.

전자는 '문자열 입력'으로, 후자는 '입력의 종료 신호'로 간주한다.

따라서 배열의 첫 인덱스에 '.'이 들어온 경우는 break; 문을 통해 반복문을 종료시켜 주어야 한다.

 

 

3. 자세한 설명은 주석으로 대체한다.

		for (int i = 0; stnc[i] != '.'; i++) {

			//여는 괄호를 입력받으면 스택에 push()
			//스택의 top은 1 증가하고, 스택에 괄호가 입력됨
			if (stnc[i] == '(' || stnc[i] == '[')
				stack[++top] = stnc[i];

			//닫는 괄호가 입력된 경우(소괄호)
			else if (stnc[i] == ')')

				//스택이 비어 있지 않으며,
				//짝이 되는 괄호가 스택에 존재한다면 pop()
				if (top > -1 && stack[top] == '(') --top;

				//아닌 경우 틀린 문장으로 간주하고
				//곧바로 while문 탈출
				else {top = -2; break;}

			//대괄호의 경우에도 위와 같게 처리
			else if (stnc[i] == ']')
				if (top > -1 && stack[top] == '[') --top;
				else { top = -2; break; }
		}

 

 

4. 위 for문으로 문장을 하나 검사할 때마다 결과값을 출력해 준다. 

		//스택이 비어 있다면 (top이 -1이라면) yes
		//맞지 않는 괄호가 입력되었거나 짝이 없어 스택이 차 있다면 no
		puts(top == -1 ? "yes" : "no");
	}

	return 0;
}

'C언어 > BAEKJOON' 카테고리의 다른 글

[백준] 2108. 통계학  (0) 2022.04.29
[백준] 1966. 프린터 큐  (0) 2022.04.28
[백준] 10845. 큐  (0) 2022.04.04
[백준] 10828. 스택  (0) 2022.04.02
[백준] 1920. 수 찾기  (0) 2022.04.02

+ Recent posts