둠치킨
코딩하는 둠치킨
둠치킨

블로그 메뉴

  • 홈
  • 분류 전체보기 (223) N
    • BOJ (176) N
      • 스택 (14)
      • 큐 (5)
      • 덱 (4)
      • 그래프 (31) N
      • 배열 (8)
      • 재귀 (12)
      • 브루트 포스 (2)
      • 그리디 알고리즘 (7)
      • 다이내믹 프로그래밍 (14) N
      • 백트래킹 (24)
      • 기하학 (4)
      • 트리 (4)
      • 구현 (14)
      • 수학 (3)
      • 맵 (1)
      • 다익스트라 (2)
      • 누적합 (5)
      • 유니온 파인드 (1)
      • 분할 정복 (2)
    • 자료구조 (14)
      • 스택 (3)
      • 큐 (5)
      • 덱 (2)
      • 그래프 (1)
      • 트리 (1)
      • 힙 (1)
      • 정렬 (1)
    • C++ (11)
      • 모두의코드 (2)
      • Effective C++ (3)
      • C++ STL (6)
    • 컴파일러 (1)
    • OS (17)
    • 컴퓨터 구조 (2)
    • Unreal Engine 5 (2)

공지사항

전체 방문자
오늘
어제

인기 글

최근 글

태그

  • BFS
  • boj
  • Bruteforce
  • C
  • C++
  • C++ STL
  • Cache Memory
  • deadlock
  • DFS
  • Effective C++
  • java
  • Mutex
  • next_permutation
  • os
  • Process
  • rotate
  • semaphore
  • spin lock
  • STL
  • STL C++
hELLO · Designed By 정상우.
둠치킨

코딩하는 둠치킨

BOJ/스택

9012번: 괄호(BOJ C/C++)

2021. 12. 23. 22:27

9012번: 괄호(BOJ C/C++)

사용 언어: C

문제

괄호 문자열(Parenthesis String, PS)은 두 개의 괄호 기호인 ‘(’ 와 ‘)’ 만으로 구성되어 있는 문자열이다. 그중에서 괄호의 모양이 바르게 구성된 문자열을 올바른 괄호 문자열(Valid PS, VPS)이라고 부른다. 한 쌍의 괄호 기호로 된 “( )” 문자열은 기본 VPS 이라고 부른다. 만일 x 가 VPS 라면 이것을 하나의 괄호에 넣은 새로운 문자열 “(x)”도 VPS 가 된다. 그리고 두 VPS x 와 y를 접합(concatenation)시킨 새로운 문자열 xy도 VPS 가 된다. 예를 들어 “(())()”와 “((()))” 는 VPS 이지만 “(()(”, “(())()))” , 그리고 “(()” 는 모두 VPS 가 아닌 문자열이다. 

여러분은 입력으로 주어진 괄호 문자열이 VPS 인지 아닌지를 판단해서 그 결과를 YES 와 NO 로 나타내어야 한다. 

입력

입력 데이터는 표준 입력을 사용한다. 입력은 T개의 테스트 데이터로 주어진다. 입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 각 테스트 데이터의 첫째 줄에는 괄호 문자열이 한 줄에 주어진다. 하나의 괄호 문자열의 길이는 2 이상 50 이하이다. 

출력

출력은 표준 출력을 사용한다. 만일 입력 괄호 문자열이 올바른 괄호 문자열(VPS)이면 “YES”, 아니면 “NO”를 한 줄에 하나씩 차례대로 출력해야 한다. 

 

첫 번째 풀이

#include <stdio.h>
#include <string.h>

int main(void)
{
	int T;
	scanf("%d",&T);
	char arr[50];
	for(int i=0;i<T;i++)
	{
		int left=0, right=0;
		scanf("%s",arr);
		int len=strlen(arr);
		for(int j=0;j<len;j++)
		{
			if(arr[j]=='(')
				left++;
			if(arr[j]==')')
				right++;
			if(right>left) 
			{
				printf("NO\n");
				break;
			}
		}
		if(right==left)
			printf("YES\n");
		else if(left>right)
			printf("NO\n");
	}
	return 0;
}

문제를 똑바로 읽지 않아서 '('와')'의 수만 같아도 되는 줄 알고 if(right>left): print(NO) 조건을 안 넣었어서 틀렸었다.

문제를 꼼꼼히 읽는 습관을 기르자.. 

 

두 번째 풀이

사실 이 문제는 스택으로 풀려 했지만 먼저 생각난 게 첫 번째 풀이(arr로 풀기)여서 일단 저 풀이로 풀었다.

 

문제를 풀기에 앞서 풀이 규칙을 세우자.

1. '(' 를 입력하면 스택에 push.

2. ')' 를 입력하면 스택에서 pop. 

   pop할때 top에 있는 문자 검사 -> '('가 아니면 성립이 안됨 -> NO

3. '(' 가 스택에 남아있는 상황, 즉 empty() 함수가 !=1 이면 -> NO 

#include <stdio.h>
#include <string.h>

#define MAX 52

typedef struct Stack{
	char arr[MAX];
	int top;
}Stack;

void init_stack(Stack* stack) //스택 초기화: top=-1
{
	stack->top=-1;
}

int full(Stack* stack)
{
	return (stack->top+1) == MAX;
}

int empty(Stack* stack)
{
	return (stack->top)==-1;
}

void push(Stack* stack, char cha)
{
	if (full(stack)) //꽉차면 더 이상 push하지 않음
		return;

	/*
	stack->top++;
	stack->arr[stack->top]=num;
	*/ //또 하나의 코드 줄이기 모먼트 발견
	
	stack->arr[++stack->top] = cha;
}

char pop(Stack* stack)
{
	if (empty(stack))
		return -1;
	
	/*
	char popcha = stack->arr[stack->top];
	stack->top--;
	*/
	
	char popcha = stack->arr[stack->top--]; 
	return popcha;
}

int main()
{
	Stack stack;

	char text[MAX], checkcha;
	int n;
	scanf("%d", &n);
	
	for(int i=0;i<n;i++)
	{
		init_stack(&stack); //for문 반복마다 stack 초기화
		int yesorno=1;      //for문 반복마다 YES, NO를 결정할 변수 초기화
		scanf("%s",text);
		for(int j=0;j<strlen(text);j++)
		{
			if(text[j]=='(')
				push(&stack, text[j]); //'(' 마다 stack에 push
			else if(text[j]==')')
			{
				checkcha = pop(&stack); //')'가 입력되면 top에 있는 문자 확인.
				if(checkcha != '(')     //'('가 아니면, 성립이 안되서 yesorno가 NO 값인 0이 된다. 
				{
					yesorno=0;
					break;
				}
			}
		}
		if(!empty(&stack)) //스택이 비어있지 않다는건, '('가 남아있는 상황이라는 것이므로 yesorno가 NO 값인 0이 된다.
			yesorno=0;
		if(yesorno==0)
			printf("NO\n");
		else
			printf("YES\n");
	}
	return 0;
}

 

느낀 점

또 주석 처리를 한 /* ~ */ 부분에 이전에 쓰던 표현보다 코드를 더 단순하게 쓸 수 있는 표현을 찾았다.

//내 코드
stack->top++;
stack->arr[stack->top]=num;

//바뀐 코드
stack->arr[++stack->top] = cha;
//내 코드
char popcha = stack->arr[stack->top];
stack->top--;

//바뀐 코드
char popcha = stack->arr[stack->top--];

사실 내가 쓰는 코드가 더 직관적으로 해석할 수 있는 면이 있긴 하지만, 더 단순한 표현들에 아직 매료되어있는 것 같다. 

 

구조체 스택을 한번 구현하고 공부해보니 구조체 스택으로 표현하는 것도 그렇게 어렵진 않다는 생각이 든다.

(https://sedangdang.tistory.com/22를 좀 참조한건 안 비밀...)

열심히 살자...!!

저작자표시 (새창열림)

'BOJ > 스택' 카테고리의 다른 글

17298번: 오큰수  (0) 2022.01.21
4949: 균형잡힌 세상(BOJ C/C++)  (0) 2021.12.27
10773: 제로(BOJ C/C++)  (0) 2021.12.25
1874번: 스택 수열(BOJ C/C++)  (0) 2021.12.19
10828번: 스택(BOJ C/C++)  (0) 2021.12.18
    'BOJ/스택' 카테고리의 다른 글
    • 4949: 균형잡힌 세상(BOJ C/C++)
    • 10773: 제로(BOJ C/C++)
    • 1874번: 스택 수열(BOJ C/C++)
    • 10828번: 스택(BOJ C/C++)
    둠치킨
    둠치킨
    코딩 공부를 위한 코딩 블로그 기록 일기

    티스토리툴바