Algorithm/[BOJ]

[Java] 백준 : 1316번 : 그룹 단어 체커

정보통신 고심이 2024. 3. 27. 09:10

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

 



접근 방법

1) 단어 개수 정수 N개 입력 받기

2) 조건문에 따라 그룹 단어 판단

3) 조건문 -> if - else 중첩

- charAt(j) != charAt(j+1) 방법으로 한글자씩 비교

- 한계 : aaba 처럼 문자열 길이가 랜덤이기에 이미 나왔던 연속돼서 나온 알파벳을 판단하기 어려웠다. 

- 이전 문자와 현재 문자를 모두 기억하는 변수를 떠올리기 어려웠다. 

 

import java.io.*;

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));
        
       int N = Integer.parseInt(br.readLine());
       int count =0;
       
       for(int i=0; i<N; i++) {
    	   String input = br.readLine();
    	   for(int j=0; j<input.length()-1; j++) {
    		   if(input.charAt(j) != input.charAt(j+1)) { // 모든 문자가 다를 경우
    			   count++;
    		   }
    		   else if(input.charAt(j) == input.charAt(j+1)) { // 같은 문자가 연속해서 나올 경우
    			   count++;
    		   }
    	   }
    	
       }
       
       bw.write(String.valueOf(count));
          
       br.close();
       bw.flush();
       bw.close();
       }
    
}

크로아티아 알파벳 문제처럼 여러 조건문을 중첩해서 푸는 문제 였는줄 알았는데

이미 나왔던 문자가 나왔을 때를 판단하기 헷갈려서 고민하다가 다른 방법을 찾아봤다.

찾은 방법은 

 

 

정답 코드 

참고한 블로그 : https://st-lab.tistory.com/69

import java.io.*;

public class Main{
       static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
       
       public static void main(String[] args) throws IOException{
	       BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
	        
	       int N = Integer.parseInt(br.readLine());
	       int count =0;
	       
	       for(int i=0; i<N; i++) {
	    	   if(check() == true) {
	    		   count++;
	    	   }
	       }
	
	       bw.write(String.valueOf(count));
	          
	       br.close();
	       bw.flush();
	       bw.close();
       }

	   public static boolean check() throws IOException { // 그룹 단어를 체크할 함수
	 	   boolean[] check = new boolean[26]; // 그룹 단어를 판단하기 위한 boolean 배열 생성 
	 	   int prev = 0;
	 	   String str = br.readLine();
	 	   
	 	   for(int i=0; i<str.length(); i++) {
	 		   int now = str.charAt(i); // 현재 문자를 저장하는 변수
	 		   
	 		   if(prev != now) { // 새로운 문자가 나온 경우 : (이전 문자 != 현재 문자) 
	 			   if(check[now -'a'] == false) { // 이전에 등장한 적 없는지 확인(now-'a' 알파벳 인덱스로 변환)
	 				   check[now -'a'] = true; // 이전에 등장하지 않았으므로 check 배열에 'true' 표시
	 				   prev = now; // 이전 문자 = 현재 문자 대입 후 다음 반복문 실행
	 			   }
	 			   else { // 이미 나온 문자일 경우 -> 그룹 단어가 아님
	 				   return false; // 거짓 반환 (종료)
	 			   }
	 		   }
	 		   
	 		  // 연속된 문자일 경우 (이전 문자 == 현재 문장)
	 		   else
	 			  continue;
	 	   }
	 	   return true;
	    }
    
}

 

  • 한계 1) aaba 처럼 문자열 길이가 랜덤이기에 이미 나왔던 연속돼서 나온 알파벳을 판단하기 어려웠다. 

해결 방법 : boolean 배열을 알파벳 개수 만큼 만들어서 그룹 단어를 판단한다. 

 

  • 한계 2) 이전 문자와 현재 문자를 모두 기억하는 변수를 떠올리기 어려웠다. 

해결 방법 :변수를 여러개 선언하는 것이 아니라, prev(이전 문자)와 now(현재 문자) 두 변수를 만들어서

새로운 문자가 나오고 이전에 등장하지 않은 문자일 경우에만, prev = now로 변수를 변경해줘서 혼란이 없도록 한다.

 

 

boolean 배열

   boolean[] check = new boolean[26];

 

true or false로 초기화 가능하다. 

 

   boolean[] check = {true, false};

 

기본값은 false이기에 check 배열은 false로 초기화

 

 

check[now-'a']

        for(int i=0; i<str.length(); i++) {
	 		   int now = str.charAt(i); // 현재 문자를 저장하는 변수
	 		   
	 		   if(prev != now) { // 새로운 문자가 나온 경우 : (이전 문자 != 현재 문자) 
	 			   if(check[now -'a'] == false) { // 이전에 등장한 적 없는지 확인(now-'a' 알파벳 인덱스로 변환)
	 				   check[now -'a'] = true; // 이전에 등장하지 않았으므로 check 배열에 'true' 표시
	 				   prev = now; // 이전 문자 = 현재 문자 대입 후 다음 반복문 실행
	 			   }
	 			   else { // 이미 나온 문자일 경우 -> 그룹 단어가 아님
	 				   return false; // 거짓 반환 (종료)
	 			   }
	 		   }
	 		   
	 		  // 연속된 문자일 경우 (이전 문자 == 현재 문장)
	 		   else
	 			  continue;
	 	   }
	 	   return true;
	    }

이전에 등장한 문자를 판단하기 위해  boolean 배열 [now-'a'] 방법을 사용한다.

사용하는 이유는 영어 알파벳을 배열의 인덱스로 사용하기 위함이다.

 

보통 영어 알파벳은 ASCII 코드에 따라 숫자로 매핑된다. 

booelan check배열의 인덱스를 영어 알파벳에 해당하는 숫자로 매핑하기 위해 'a'(ASCII : 97) 를 빼준다.

 

check 배열은 모두 false로 초기화된 상태 

input = aba

check ['a' - 'a'] = check[0] = false => 이전에 나온적X 알파벳 => check[0] = true

check['b' - 'a'] =  check[1] = false => 이전에 나온적X 알파벳 => check[1] = true

check['a' - 'a']  = check[2] = false => a가 이미 나왔던 문자로 판단 => 그룹 단어X => false 반환 => 종료 

 

문자를 숫자로 매핑하여 컴퓨터가 쉽게 처리하기 위해 아스키 코드를 사용한다.

게다가 알파벳 'a' ~ 'z' 아스키 코드 값은 연속적이고,   각 알파벳에 a를 뺄 경우 0~25까지 연속된 정수 값으로 매핑할 수 있기에 알파벳을 인덱스로 사용하는 배열을 구현한 것이다.