백준 - 17413번(단어 뒤집기 2)

최지홍·2022년 1월 28일
0

백준

목록 보기
8/145

문제 출처: https://www.acmicpc.net/problem/17413


문제

  • 문자열 S가 주어졌을 때, 이 문자열에서 단어만 뒤집으려고 한다.

  • 먼저, 문자열 S는 아래와과 같은 규칙을 지킨다.

  1. 알파벳 소문자('a'-'z'), 숫자('0'-'9'), 공백(' '), 특수 문자('<', '>')로만 이루어져 있다.
  2. 문자열의 시작과 끝은 공백이 아니다.
  3. '<'와 '>'가 문자열에 있는 경우 번갈아가면서 등장하며, '<'이 먼저 등장한다. 또, 두 문자의 개수는 같다.
    태그는 '<'로 시작해서 '>'로 끝나는 길이가 3 이상인 부분 문자열이고, '<'와 '>' 사이에는 알파벳 소문자와 공백만 있다. 단어는 알파벳 소문자와 숫자로 이루어진 부분 문자열이고, 연속하는 두 단어는 공백 하나로 구분한다. 태그는 단어가 아니며, 태그와 단어 사이에는 공백이 없다.

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) throws Exception {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder(reader.readLine()).append(" ");
        String pattern = "[a-z0-9]+";
        int left = 0;
        boolean flag = true; // 연달아 구분자가 나오는 처리(true -> 정상진행, false -> 구분자 처리)
        boolean isContinue = false; // <> 처리(true -> 생략해야되는 문자)

        // 연달아 나온다면? <> 처리...
        for (int i = 0; i < sb.length(); i++) {
            if (!isContinue) { // 생략해야되는 부분이 아닌 경우
                if (!sb.substring(i, i + 1).matches(pattern)) { // 패턴과 매치되지 않는 경우 -> 구분자인 경우
                    if (sb.substring(i, i + 1).equals("<")) { // "<" 모양인지 확인
                        isContinue = true; // 맞을 경우 뒤에 나오는 것들을 생략해야하므로 true로 변경
                    }
                    if (flag) { // 처음나오는 구분자인 경우(정상처리면 true이므로)
                        StringBuilder temp = new StringBuilder(sb.substring(left, i)); // 구분자 전까지의 내용
                        sb.replace(left, i, temp.reverse().toString()); // 뒤집기
                        flag = false; // 구분자를 처리하였으므로 false
                        left = i + 1; // left index 이동
                    } else { // 연달아 나오는 구분자인 경우
                        left = i + 1; // left index만 옮기고 끝
                        continue;
                    }
                } else { // 패턴과 일치하는 경우
                    flag = true; // flag를 true로 둠
                    continue;
                }
            } else if (sb.substring(i, i + 1).equals(">")) { // 생략해야되는 부분 진행 중 ">"를 만난 경우
                left = i + 1; // left index 옮기고
                isContinue = false; // 생략 그만
            } else { // 생략해야되는 부분인 경우
                continue;
            }
        }

        System.out.println(sb);
    }

}

  • 나름 괜찮은 로직이라 생각했으나 메모리와 시간이 엄청나다.
  • StringTokenizer를 활용한 분의 코드를 보았다. 상당히 엄청나다...
  • StringTokenizer의 생성자의 세번째 인자를 true로 주면 delimiter를 반환함을 처음 알게 되었다.
profile
백엔드 개발자가 되자!

0개의 댓글