[9046] 복호화

않새준·2025년 1월 19일

[백준 9046]
https://www.acmicpc.net/problem/9046

입력문 중 가장 빈도가 높은 알파벳을 찾고 복호화 과정을 거친 알파벳을 출력하는 문제이다.

문제를 풀기 전 간단하게 알고리즘에 대해 끄적여봤다.




가장 처음으로 한 일은 복호화를 위해 평문과 암호문을 ArrayList에 저장하기로 했다.

		// 암호화 문자열
    	String substitution_temp = "wghuvijxpqrstacdebfklmnoyz";
    	// 평소 문자열
    	String original_temp = "abcdefghijklmnopqrstuvwxyz";
    	
    	// 문자열 to ArrayList
    	char[] substitution = new char[substitution_temp.length()];
    	char[] original = new char[original_temp.length()];
    	
    	for (int i = 0; i < substitution.length; i++) {
    		substitution[i] = substitution_temp.charAt(i);
    		original[i] = original_temp.charAt(i);
    	}
    	

처음부터 문자열을 배열이나 ArrayList에 넣지 않고 변환한 이유는 {'a', 'b', 'c'} 이런식으로 따옴표로 나눠서 배열을 선언하기 귀찮았기 때문이다.


이제 여러가지 변수를 생성하였다.

count, request : 사용자의 입력을 저장
number : 빈도수를 기록하기 위한 배열
max_index : 가장 높은 빈도수를 가진 인덱스 값을 저장할 배열
det : 가장 높은 빈도수의 값이 여러 개일 경우 판별하기 위한 boolean 변수

작성한 코드는 아래와 같다.

		int count = sc.nextInt();
    	sc.nextLine();
    	
    	
    	for(int j = 0; j < count; j++) {
    		// a ~ z 크기의 배열 생성 -> 빈도 표기 
        	int[] number = new int[26];
        	int max_index = 0;	// 높은 빈도의 알파벳 인덱스를 저장(초기 0)
        	boolean det = true;	// 빈도 동일 시 false로 변경
        	
    		String request = sc.nextLine();
    		for (int k = 0; k < request.length(); k++) {
                char ch = request.charAt(k); 
                if (Character.isLetter(ch)) { // 공백 처리
                    number[ch - 'a']++; // 해당 알파벳의 인덱스 값을 계산하여 배열에 저장
                }
            }

공백을 처리하기 위해.charAt 메서드를 사용하였다.

해당 메서드는 사용 방법을 몰라 구글링을 사용하였다...

그렇게 공백을 제거한 문자는 알파벳의 인덱스를 계산하여 배열에 빈도수를 증가시킨다.


마지막으로 가장 빈번하게 작성된 알파벳을 출력해보자.
			// 최빈 알파벳 구하기
    		for (int r = 1; r < number.length; r++) {
    			// max_index를 변경하며 true로 처리한다.
    			if (number[r] > number[max_index]) {
    				max_index = r;
    				det = true;
    			}
    			// 동일한 값의 경우에는 false로 변경한다.
    			else if (number[r] == number[max_index]) {
    				det = false;
    			}
    		}
    		// det 여부에 따라 출력을 달리한다.
    		if(det == true) {
    			System.out.println(original[max_index]);
    		}
    		else {
    			System.out.println("?");
    		}

max_index 변수를 1로 선언하였으니 1번째 인덱스부터 순회하도록 한다.

그렇게 만약 순회 중 더 큰 값을 발견하면 max_index를 업데이트 하며 boolean을 true로 유지 / 변경 한다.

만약 동일한 값의 경우에는 false로 변경한다.

이제 해당 boolean에 따라 조건을 나누어 정답을 출력하였다.



[코드 전문]
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
    	Scanner sc = new Scanner(System.in);
    	
    	// 암호화 문자
    	//String substitution_temp = "wghuvijxpqrstacdebfklmnoyz";
    	// 평소 문자
    	String original_temp = "abcdefghijklmnopqrstuvwxyz";
    	
    	// 배열 to ArrayList
    	//char[] substitution = new char[substitution_temp.length()];
    	char[] original = new char[original_temp.length()];
    	
    	for (int i = 0; i < original.length; i++) {
    		//substitution[i] = substitution_temp.charAt(i);
    		original[i] = original_temp.charAt(i);
    	}
    	
    	
    	int count = sc.nextInt();
    	sc.nextLine();
    	
    	
    	for(int j = 0; j < count; j++) {
    		// a ~ z 크기의 배열 생성 -> 빈도 표기 
        	int[] number = new int[26];
        	int max_index = 0;	// 높은 빈도의 알파벳 인덱스를 저장(초기 0)
        	boolean det = true;	// 빈도 동일 시 false로 변경
        	
    		String request = sc.nextLine();
    		for (int k = 0; k < request.length(); k++) {
                char ch = request.charAt(k); 
                if (Character.isLetter(ch)) { // 공백 처리
                    number[ch - 'a']++; // 해당 알파벳의 인덱스 값을 계산하여 배열에 저장
                }
            }
    		// 최빈 알파벳 구하기
    		for (int r = 1; r < number.length; r++) {
    			// max_index를 변경하며 true로 처리한다.
    			if (number[r] > number[max_index]) {
    				max_index = r;
    				det = true;
    			}
    			// 동일한 값의 경우에는 false로 변경한다.
    			else if (number[r] == number[max_index]) {
    				det = false;
    			}
    		}
    		// det 여부에 따라 출력을 달리한다.
    		if(det == true) {
    			System.out.println(original[max_index]);
    		}
    		else {
    			System.out.println("?");
    		}
    	}
    }
}

해당 코드를 통해 문제를 해결할 수 있었다!



깃허브에 푸시 후 PR까지 모두 완료한 이후 깨닫게 된 점이 있다.

해당 코드는 문제는 없지만 상당히 비효율적으로 작성되어 있다.

처음 암호화 된 문자가 저장된 substitution 배열은 코드에서 사용되지 않는다.

또한, 시간복잡도가 O(n^2) 이므로 상당히 비효율적인 코드이다.

정답이긴 하나 코드를 정말 비효율적으로 작성한 것 같아 많은 수정이 필요해 보인다.

추후에 다시 수정해서 올려야겠다.

그리고 깃허브 리포지토리에 단순히 커밋 푸시를 통해 올리면 되는 줄 알았지만 포크와 PR을 사용해서 올려야 하는 규칙이 존재했기에 해당 규칙을 따라야 했다.

그렇게 fork, clone, PR 까지 다양한 시행착오를 거쳐 해냈지만 이게 맞게 잘 적용된 건지는 잘 모르겠다..ㅠ

끗.

2개의 댓글

comment-user-thumbnail
2025년 1월 19일

암호화된 문자를 복호화하라는 내용은 문제에 없어서 배열을 따로 만들지 않아도 될 거 같아요~
그리고 크롬에서 제공하는 백준 허브 사용하면 깃허브에 자동 푸시해주니까 찾아보시면 좋을 것 같아요!
좋은 글 잘 보고 갑니다 :)

1개의 답글