[알고리즘 문제풀이] 백준 1662 압축 ( 도와주세요 🙏🏻 )
이 문제는 실은 며칠전에 푼 문젠데 찜찜했던 부분이 있어서 다시 풀었다.
도와주세요 🙏🏻 궁금한 부분 !
그리고 다시 풀면서 정규식으로 하면 문자열이 너무 길어져서 시간 초과가 나겠지 하면서도 한 번 테스트를 해보고 싶어서 풀어보았는데 채점 1%에서 실패가 떴다.. 질문에 올라온 반례들을 다 실행시켜봐도 문제가 없었는데.. 그리고 시간이 오래 걸려서 문제지 가장 압축을 실제로 푸는 방법이라 반례가 문제인 거 같지는 않은데 뭐가 문제일까 궁금하다..
정규식 풀이 코드도 아래 첨부할테니 문제를 알겠는 분들은 답변 남겨주시면 감사할 거 같습니다.
문제
압축되지 않은 문자열 S가 주어졌을 때, 이 문자열중 어떤 부분 문자열은 K(Q)와 같이 압축 할 수 있다. K는 한자리 정수이고, Q는 0자리 이상의 문자열이다. 이 Q라는 문자열이 K번 반복된다는 뜻이다. 압축된 문자열이 주어졌을 때, 이 문자열을 다시 압축을 푸는 프로그램을 작성하시오.
입력
첫째 줄에 압축된 문자열 S가 들어온다. S의 길이는 최대 50이다. 문자열은 (, ), 0-9사이의 숫자로만 들어온다.
출력
첫째 줄에 압축되지 않은 문자열의 길이를 출력한다. 이 값은 int범위다.
예제
입력 1
33(562(71(9)))
출력 1
19
풀이 방법
괄호 안에 있는 문자열을 괄호 앞의 숫자만큼 반복해야 하는 것이기 때문에 먼저 괄호 안에 있는 문자열을 찾아내야한다 ! 그렇기 때문에 괄호 쌍을 찾아주기 위해서 Stack을 사용하여 문제를 풀어보았다.
문자열을 반복하며 현재 문자를 스택에 넣어주었다. 이 때, 현재 문자가 ')' 닫는 괄호인 경우에는 '(' 여는 괄호가 나올 때까지 스택을 pop 해주었다 ! 그러면서 괄호 사이의 문자가 몇 개인지 카운트 해주었다. 여는 괄호를 만나면 하나 더 pop을 하여 그 숫자와 문자열의 길이를 곱해주어 압축을 풀어준다.
이 때, 압축된 문자열의 형태가 재귀처럼 괄호 안에 또 괄호가 있을 수 있는 구조이기 때문에, 압축을 푼 문자열의 길이를 다시 스택에 넣어주었다. 단, 이것이 문자가 아닌 길이라는 것을 구분하기 위해 * 구분자를 붙여주었다.
문자열을 반복하며 압축을 모두 푼 후에는 스택을 탐색하면서 남아있는 문자나 압축이 풀린 문자열의 길이를 반영하여 최종 문자열의 길이를 구해주었다 !
코드
import java.io.*;
import java.util.Stack;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String target = br.readLine();
Stack<String> stack = new Stack<>();
int len;
for(int i=0; i<target.length(); i++){
if(target.charAt(i) == ')'){
len = 0;
while (!stack.peek().equals("(")){
if(stack.peek().charAt(0) == '*') len+=Integer.parseInt(stack.pop().substring(1));
else{
stack.pop();
len++;
}
}
stack.pop();
stack.push("*" + (len*Integer.parseInt(stack.pop())));
}else{
stack.push(String.valueOf(target.charAt(i)));
}
}
len = 0;
while(!stack.isEmpty()){
if(stack.peek().charAt(0) == '*') len+=Integer.parseInt(stack.pop().substring(1));
else{
stack.pop();
len++;
}
}
bw.write(len + "\n");
bw.flush();
bw.close();
br.close();
}
}
정규식 풀이 코드
간단한 풀이를 덧붙이자면, (Q)를 찾아서 K(Q)부분 전체를 Q.repeat(K)로 replace해주는 코드이다. 즉 진짜 압축을 푼 문자열을 만들어서 길이를 출력하는 형태이다 ! 물론 괄호 안에 또 괄호가 있는 형태에도 닫는 괄호를 먼저 만나는 경우부터 수행하기 때문에 가장 안의 레벨부터 압축을 풀게 되어있어 문제가 없다 !
그치만 채점 결과 1%부터 실패가 뜬다.. 실패해도 시간초과가 맞는 것 같은데 ! 뭔가 실수를 한 것이 있는 거 같은데 모르겠다.. 아시는 분 도와주세요 🙏🏻
import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String target = br.readLine();
Pattern pattern = Pattern.compile("[(][0-9]+[)]"); // 정규식 이용해서 (숫자) 형태의 패턴 찾기
Matcher matcher;
while (true){
matcher = pattern.matcher(target);
if(!matcher.find()) break; // 더이상 위의 패턴 형태의 문자열이 없으면 종료
target = target.replace(target.charAt(matcher.start()-1) + matcher.group(), matcher.group().substring(1, matcher.group().length()-1).repeat(target.charAt(matcher.start()-1)-'0')); // 찾은 패턴에서 괄호를 제거한 숫자부분만 여는 괄호 앞의 숫자만큼 반복한 문자열로 replace
}
bw.write(target.length() + "\n");
bw.flush();
bw.close();
br.close();
}
}
Author And Source
이 문제에 관하여([알고리즘 문제풀이] 백준 1662 압축 ( 도와주세요 🙏🏻 )), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@cgw0519/알고리즘-문제풀이-백준-1662-압축-도와주세요저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)