
내가 생각했을때 문제에서 원하는부분
The first line of input contains the 26 lowercase letters 'a' through 'z' in the order they appear in the cowphabet.
The next line contains the string of lowercase letters that Farmer John heard Bessie say.
This string has length at least 1 and at most 1000.
Print the minimum number of times Bessie must have hummed the entire cowphabet.
내가 이 문제를 보고 생각해본 부분
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));: 이 코드는 사용자로부터 입력을 받기 위한 통로를 설정하는 과정이다.
System.in: 표준 입력 스트림을 의미하며, 일반적으로 키보드를 통해 입력되는 데이터를 가리킨다.
InputStreamReader: System.in이 바이트(byte) 단위로 읽어들이는 데이터를 우리가 이해할 수 있는 문자(character) 단위로 변환해 준다.
BufferedReader: 문자 단위로 읽어온 데이터를 임시 저장 공간(버퍼)에 모아두었다가, 한 번에 여러 문자를 처리하거나 한 줄 전체를 읽어올 수 있게 해주는 아주 편리한 도구이다.
이렇게 br이라는 BufferedReader 객체를 만들어두면, 이후에 br.readLine() 같은 메서드를 사용해서 쉽고 빠르게 한 줄씩 입력을 읽어올 수 있게 된다.
String cowphabetOrder = br.readLine();: br.readLine() 메서드를 사용해서 입력의 첫 번째 줄(cowphabet의 순서)을 읽어와 cowphabetOrder라는 String 변수에 저장한다.
이 문자열은 Bessie가 'a'부터 'z'까지 26개의 글자를 흥얼거리는 고유한 순서를 나타낸다.
Map<Character, Integer> charOrder = new HashMap<>();: charOrder라는 이름의 HashMap 객체를 새로 생성한다.
이 맵은 Character(문자)를 키로, Integer(정수)를 값으로 가질 거다.
이 맵의 목적은 각 알파벳 문자가 cowphabetOrder에서 몇 번째 순서(인덱스)로 나타나는지 저장하여 나중에 빠르게 찾아볼 수 있게 하는 것이다.
for (int i = 0; i < cowphabetOrder.length(); i++) { ... }: 이 for 루프는 cowphabetOrder 문자열의 각 문자를 처음부터 끝까지 하나씩 반복하며 처리한다.
cowphabetOrder.charAt(i): cowphabetOrder 문자열에서 현재 i번째 위치에 있는 문자를 가져온다.
charOrder.put(cowphabetOrder.charAt(i), i);: 가져온 문자를 charOrder 맵의 '키'로, 그 문자가 문자열에서 몇 번째 위치에 있었는지를 나타내는 인덱스 i를 '값'으로 저장한다.
이렇게 해두면, 예를 들어 charOrder.get('m')을 호출하면 'm'이 cowphabet에서 몇 번째로 나오는지 바로 알 수 있게 된다.
String heardString = br.readLine();: 다시 한번 br.readLine()을 사용하여 입력의 두 번째 줄(Farmer John이 들은 문자열)을 읽어와 heardString이라는 변수에 저장한다.
이 문자열은 Bessie가 흥얼거리는 소리 중 John이 기억하는 부분 수열이다.
int hums = 1;: hums라는 정수형 변수를 선언하고 1로 초기화한다.
이 변수는 Bessie가 cowphabet 전체를 흥얼거린 최소 횟수를 세는 역할을 한다.
Farmer John이 어떤 소리라도 들으려면 Bessie는 최소한 한 번은 cowphabet을 흥얼거려야 하기 때문에, 초기값을 1로 설정하는 것이 합리적이다.
for (int i = 1; i < heardString.length(); i++) { ... }: heardString의 두 번째 문자부터(i가 1부터 시작하는 이유) 마지막 문자까지 반복하면서 각 문자를 이전 문자와 비교하는 루프이다.
첫 번째 문자는 이미 초기 hums = 1에 포함되었으므로, 두 번째 문자부터 비교를 시작하면 된다.
char prevChar = heardString.charAt(i - 1);: 현재 루프의 i번째 문자 바로 직전에 John이 들었던 문자를 prevChar 변수에 저장한다.
char currentChar = heardString.charAt(i);: 현재 루프에서 비교의 대상이 되는 i번째 문자를 currentChar 변수에 저장한다.
if (charOrder.get(currentChar) <= charOrder.get(prevChar)) { hums++; }: 이 if 조건문이 이 문제의 핵심 로직이다.
charOrder.get(currentChar): 현재 문자의 cowphabet 순서를 맵에서 가져온다.
charOrder.get(prevChar): 이전 문자의 cowphabet 순서를 맵에서 가져온다.
만약 currentChar의 cowphabet 순서가 prevChar의 순서보다 작거나 같다면 (<=) 이 조건이 참이 된다.
이는 Bessie가 prevChar를 흥얼거린 후에, cowphabet 순서상 prevChar보다 먼저 나오거나 같은 위치에 있는 currentChar를 다시 흥얼거릴 수 없다는 것을 의미한다.
Bessie는 cowphabet을 항상 순서대로만 흥얼거리기 때문이다.
이런 상황이 발생했다는 것은, Bessie가 이전에 흥얼거리던 cowphabet을 마무리하고, 새로운 cowphabet 흥얼거림을 처음부터 다시 시작했다는 뜻으로 해석해야 한다.
따라서 hums 값을 1 증가시켜 흥얼거림 횟수를 늘린다.
System.out.println(hums);: heardString 전체를 분석하여 최종적으로 계산된 hums 값(Bessie가 cowphabet을 흥얼거린 최소 횟수)을 콘솔에 출력한다.
br.close();: BufferedReader를 통해 열었던 입력 스트림을 닫아준다.
코드로 구현
package baekjoon.baekjoon_32;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
// 백준 20973번 문제
public class Main1277 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 1. Cowphabet 순서를 입력받고 각 문자의 순서(인덱스)를 Map에 저장합니다.
// 예를 들어, cowphabet = "zyxw..." 이면
// map['z'] = 0, map['y'] = 1, map['x'] = 2 ... 이런 식으로 저장됩니다.
String cowphabetOrder = br.readLine();
Map<Character, Integer> charOrder = new HashMap<>();
for (int i = 0; i < cowphabetOrder.length(); i++) {
charOrder.put(cowphabetOrder.charAt(i), i);
}
// 2. Farmer John이 들은 문자열을 입력받습니다.
String heardString = br.readLine();
// 3. 최소 흥얼거림 횟수를 1로 초기화합니다.
// 첫 번째 문자는 어떤 경우에도 첫 번째 흥얼거림에 포함되므로 1부터 시작합니다.
int hums = 1;
// 4. John이 들은 문자열의 두 번째 문자부터 마지막 문자까지 순회합니다.
for (int i = 1; i < heardString.length(); i++) {
char prevChar = heardString.charAt(i - 1); // 이전 문자
char currentChar = heardString.charAt(i); // 현재 문자
// 5. 이전 문자의 cowphabet 순서와 현재 문자의 cowphabet 순서를 비교합니다.
// 만약 현재 문자의 순서가 이전 문자의 순서보다 같거나 앞에 있다면
// (즉, charOrder.get(currentChar) <= charOrder.get(prevChar))
// Bessie는 새로운 cowphabet을 흥얼거리기 시작해야 합니다.
if (charOrder.get(currentChar) <= charOrder.get(prevChar)) {
hums++; // 흥얼거림 횟수를 1 증가시킵니다.
}
}
// 6. 계산된 최소 흥얼거림 횟수를 출력합니다.
System.out.println(hums);
br.close();
}
}
코드와 설명이 부족할수 있습니다. 코드를 보시고 문제가 있거나 코드 개선이 필요한 부분이 있다면 댓글로 말해주시면 감사한 마음으로 참고해 코드를 수정 하겠습니다.