자료구조 공부/String

백준 2800 (괄호 제거) - 조합알고리즘, Stack

kdhoooon 2021. 4. 30. 15:26

문제


어떤 수식이 주어졌을 때, 괄호를 제거해서 나올 수 있는 서로 다른 식의 개수를 계산하는 프로그램을 작성하시오.

이 수식은 괄호가 올바르게 쳐져 있다. 예를 들면, 1+2, (3+4), (3+4*(5+6))와 같은 식은 괄호가 서로 쌍이 맞으므로 올바른 식이다.

하지만, 1+(2*3, ((2+3)*4 와 같은 식은 쌍이 맞지 않는 괄호가 있으므로 올바른 식이 아니다.

괄호를 제거할 때는, 항상 쌍이 되는 괄호끼리 제거해야 한다.

예를들어 (2+(2*2)+2)에서 괄호를 제거하면, (2+2*2+2), 2+(2*2)+2, 2+2*2+2를 만들 수 있다. 하지만, (2+2*2)+2와 2+(2*2+2)는 만들 수 없다. 그 이유는 쌍이 되지 않는 괄호를 제거했기 때문이다.

어떤 식을 여러 쌍의 괄호가 감쌀 수 있다.

 

 

 

 

풀이


Stack을 이용해서 풀면 쉽게 풀 수 있는 문제였지만, 반례를 생각하지 못해서 많이 틀렸다.

 

반례를 먼저 짚고 가면,

(((0))) 일 경우, ((0)), (0), 0 이 나와야한다. 

하지만, 나는 ((0)) 이 중복되게 출력이 됐었다.

이 부분을 잘 생각해서 풀면 다른 오류는 없다.

 

괄호의 위치를 저장하는 코드다.

list = new ArrayList<location>();
for(int i = 0 ; i < me.length ; i++) {
	
	if(me[i] == '(') {
		stack.add(i);
	}
	else if(me[i] == ')') {
		int a = stack.pop();
		list.add(new location(a, i));
	}
}

location 이라는 클레스를 만들어서 한상의 괄호의 시작지점과 끝지점을 저장해 두었다.

Stack은 나중에 들어간 값이 먼저 나오므로 가장 나중에 저장된 괄호가 ')'를 만났을 때 가장 먼저 나온다.

 

그렇게 저장된 리스트를 가지고 조합알고리즘을 했다.

static void Combination(List<location> list, List<location> result, int cnt, int idx, int r) {
	
	if( r == cnt ) {
		boolean[] check = new boolean[me.length];
		for(int i = 0 ; i < result.size() ; i++) {
			check[result.get(i).a] = true;
			check[result.get(i).b] = true; 
		}
		
		StringBuilder stringBuilder = new StringBuilder();
		for(int i = 0 ; i < me.length ; i++) {
			if(!check[i]) {
				stringBuilder.append(me[i]);
			}
		}
		
		if(!set.contains(stringBuilder.toString())) {
			set.add(stringBuilder.toString());
		}
		
		return;
	}
	
	for(int i = idx ; i < list.size(); i++) {
		
		result.add(list.get(i));
		Combination(list, result, cnt, i + 1, r + 1);
		result.remove(result.size() - 1);
	}
	
	return;
}

String 으로 더해도 되지만 StringBuilder 가 String 보다 시간이 빨랐던걸로 기억해서 StringBuilder로 했다.

해당 String이 중복되는지는 HashSet<String>을 이용해서 확인했다.

 

이렇게 중복없이 String을 저장하여, 사전순으로 정렬하여 출력하면 된다.

 

<전체코드>

import java.io.*;
import java.util.*;

public class Main {	

	static StringBuilder sb = new StringBuilder();
	
	static class location{
		
		int a, b;
		
		public location(int a, int b) {
			this.a = a;
			this.b = b;
		}
	}
	
	static List<location> list;
	static List<location> result;
	static char[] me;
	static int size = 0;
	static HashSet<String> set = new HashSet<String>();
	public static void main(String[] args) throws IOException{
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
		
		me = bufferedReader.readLine().toCharArray();
		
		Stack<Integer> stack = new Stack<Integer>();
		list = new ArrayList<location>();
		for(int i = 0 ; i < me.length ; i++) {
			
			if(me[i] == '(') {
				stack.add(i);
			}
			else if(me[i] == ')') {
				int a = stack.pop();
				list.add(new location(a, i));
			}
		}
		
		
		result = new ArrayList<location>();
		size = list.size();
		for(int i = 1 ; i <= size ; i++ ) {
			Combination(list, result, i, 0, 0);
		}
		
		List<String> answer = new ArrayList<String>();
		for(String string : set) {
			answer.add(string);
		}
		
		Collections.sort(answer);
		
		for(String ans : answer) {
			sb.append(ans + "\n");
		}
		System.out.println(sb);
	}
	
	
	static void Combination(List<location> list, List<location> result, int cnt, int idx, int r) {
		
		if( r == cnt ) {
			boolean[] check = new boolean[me.length];
			for(int i = 0 ; i < result.size() ; i++) {
				check[result.get(i).a] = true;
				check[result.get(i).b] = true; 
			}
			
			StringBuilder stringBuilder = new StringBuilder();
			for(int i = 0 ; i < me.length ; i++) {
				if(!check[i]) {
					stringBuilder.append(me[i]);
				}
			}
			
			if(!set.contains(stringBuilder.toString())) {
				set.add(stringBuilder.toString());
			}
			
			return;
		}
		
		for(int i = idx ; i < list.size(); i++) {
			
			result.add(list.get(i));
			Combination(list, result, cnt, i + 1, r + 1);
			result.remove(result.size() - 1);
		}
		
		return;
	}
}

'자료구조 공부 > String' 카테고리의 다른 글

[프로그래머스] 신규아이디 추천  (0) 2021.05.05
백준 16172 (나는 친구가 적다(Large))  (0) 2021.04.30
백준 2002 (추월)  (0) 2021.04.24
백준 4354 (문자열 제곱)  (0) 2021.04.21
백준 1305 (광고)  (0) 2021.04.21