본문 바로가기

알고리즘

(백준) 문자열 다루기

윈도우즈 명령프롬프트(cmd)에서 dir 명령

directory의 약어로 현재 위치한 폴더의 서브디렉토리(하위 디렉토리)와 파일들을 모두 표시하게 하는 명령어다.


문자열 다루는 알고리즘

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

윈도우즈 명령 프롬프트(cmd)에 dir 다음 작성한 패턴이(검색어) 무엇인지 검색결과를 보고 추출하는 문제String타입으로 첫 번째 줄에는 파일의 갯수(N), 두 번째줄부터 파일명들이 N개의 줄까지 라인단위로 나열됨.N은 50보다 작거나 같은 자연수, 파일 이름의 길이는 모두 같고 길이는 최대 50까지다.파일 이름은 알파벳 소문자와 '.'으로만 이루어져 있다.

 

문제가 어려웠던 점

1. 전달받는 값의 타입을 String으로 두어야 할지 String[]로 받아야 할지부터가 헷갈렸음.결국 String 타입으로 받아서 라인단위로 쪼개어 String[] 배열을 반환받는 작업을 진행했음.2. 각 파일명의 문자 단위를 비교하는 로직을 작성하는 처음부터 쉽지 않았던 것이 기준을 어디에 두어야 할지 감이 잡히지 않음.결국 gpt의 도움을 받아 첫 파일명의 첫 문자열을 전달받아 반복문을 돌렸다.

 

실습 코드

 

package algo2025.august;

import java.util.Arrays;

public class Cmd {
    public String getPattern(String filesInfo) {
        String[] fileNames = fileNames(filesInfo);
        return buildPattern(fileNames);
    }

    // 두 번째 인덱스부터(1) 끝까지(끝의 값을 포함)
    private String[] fileNames(String filesInfo) {
        int count = fileCount(filesInfo); // 파일명 갯수
        // 파일명 갯수와 파일명들이 String 타입으로 배열에 포함되어 있다.
        String[] original = parseFileInfo(filesInfo);
        return Arrays.copyOfRange(original, 1, (count+1));
    }

    // 첫 번째 인덱스에 담긴 값이 파일의 갯수
    private int fileCount(String filesInfo) {
        String[] parsedFileInfo = parseFileInfo(filesInfo);
        return Integer.parseInt(parsedFileInfo[0]);
    }

    // 인자로 전달받은 파일정보를 라인단위로 쪼개서 전달받기
    private String[] parseFileInfo(String filesInfo) {
        return filesInfo.split("\\n");
    }

    // String[] fileNames(String filesInfo)의 반환값이 인자
    private String buildPattern(String[] fileNames) {
        int fileCount = fileNames.length; // 파일명 갯수
        int length = fileNames[0].length(); // 파일명의 문자 갯수
        StringBuilder pattern = new StringBuilder();

        if(fileCount==1) return fileNames[0];

        for(int i=0; i<length; i++) {
            // 첫 파일명의 첫 번째 문자를 담은 currentChar
            char currentChar = fileNames[0].charAt(i);
            boolean flag = true;

            for(int j=1; j<fileCount; j++) {
                // 첫 파일명의 첫 번째 문자와
                // (ex. fileNames[1].charAt(0) 두 번째 파일명의 첫 번째 문자가 다르다면)
                // ? 물음표로 대체한다.
                if(currentChar != fileNames[j].charAt(i)) {
                    flag = false;
                    break;
                }
            }
            pattern.append(flag? currentChar: '?');
        }
        return pattern.toString();
    }

    public static void main(String[] args) {
        Cmd cmd = new Cmd();
        // String input = "3\nconfig.syd\nconfig.cmd\nconfig.yyd";
        String input = "1\nconfig.syd";
        String pattern = cmd.getPattern(input);
        System.out.println(pattern);
    }
}

 

해설지보고 다시 정리해보기

- 첫 번째 파일 이름을 기준으로 설정한다.- 각 문자 위치별로 N개의 파일을 비교한다.- 동일하면 그대로, 다르면 '?'를 결과에 추가한다.

    public static void main(String[] args) {
        try(BufferedReader br= new BufferedReader(new InputStreamReader(System.in))) {
            int fileCount = Integer.parseInt(br.readLine());
            String[] files = new String[fileCount];

            for(int i=0; i<fileCount; i++) {
                files[i] = br.readLine();
            }

            if(fileCount == 1) {
                System.out.println(files[0]);
                return;
            }

            StringBuilder pattern = new StringBuilder();

            for(int i=0; i < files[0].length(); i++) {
                char currentChar = files[0].charAt(i);
                boolean matches = true;

                for(int compareFileIndex=1; compareFileIndex < files.length; compareFileIndex++) {
                    if(currentChar != files[compareFileIndex].charAt(i)) {
                        matches = false;
                        break;
                    }
                }

                pattern.append(matches?currentChar:'?');
            }

            System.out.println(pattern);

        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

 

들어본적은 있으나 제대로 활용하지 못하는, 공부해야할 점

BufferedReader와 InputStreamReader 클래스BufferedReader.readLine() 메서드


BufferedReader 

문자, 배열, 줄을 효과적으로 읽을 수 있도록 문자들을 버퍼링하면서 문자 입력 스트림으로부터 텍스트를 읽어들인다

→ 문자 입력 스트림에서 글자들을 읽어올 때, 한 글자씩 바로 처리하는 게 아니라,

여러 글자를 한 번에 읽어서 임시 버에(buffer) 저장해두고,

그 버퍼에서 문자(char), 문자 배열(char[]), 또는 한 줄 단위로 읽어들인다. 
- 문자 입력 스트림은 외부 텍스트 데이터, ex. 파일, 네트워크 등 
- 버퍼링은 여러 문자를 한 번에 읽어서 임시 저장소(버퍼)에 저장하는 것 
- 읽는다는 것은 프로그램이 문자, 배열, 줄 단위로 꺼낸다는 것을 의미 

 

FileReaders, InputStreamReaders와 같은 Reader타입의 read() 메서드 수행은

비용이 많이 들기 때문에 BufferedReader로 래핑하는 것을 추천한다고 한다. 
ex. new BufferedReader(new InputStreamReader(System.in)) 
BufferedReader 인스턴스는 기본 생성자로 생성하지 못한다.

 

매개변수로 Reader 타입 인스턴스를 전달하거나 
Reader 타입 인스턴스, 버퍼 사이즈를 전달해서 생성할 수 있다.


BufferedReader를 사용하는 이유 
외부로부터 데이터를 읽어들일 때 일정 단위로 텍스트를 읽어들여
버퍼(임시 저장소)에 저장하고, 버퍼로부터 데이터를 읽어들이는,
효율적인 읽고, 쓰기 작업을 수행하기 위해서다.
(시간 단축은 곧 비용 절감으로 이어진다)

반응형

'알고리즘' 카테고리의 다른 글

계단을 오르는 경우의 수를 구하기  (5) 2025.08.11
Stack과 Queue  (7) 2025.08.06
이상한 문자 만들기  (2) 2025.07.01
3진법 뒤집기  (2) 2025.06.27
행렬의 덧셈  (2) 2025.06.23