컴퓨터 공부/📚 Baekjoon(백준)

[백준/알고리즘/python/java] 1316번 - 그룹 단어 체커

letzgorats 2021. 1. 27. 04:23

이미지를 누르면 문제링크를 보실 수 있습니다.
1316 - 그룹 단어 체커

<자바>


우선 애를 먹은 문제이다.
boolean을 잘 활용해야 한다. 여기서는 int 형을 이용해서 0과 1을 사용했는데,
함수를 만들면서 check 포인트를 설정하는 알고리즘에 익숙해져야 한다.

 

(자바 코드)

import java.util.Scanner;
public class Main{
	static int[] check(int alphabet[]) {
		for(int i=0;i<alphabet.length;i++) {
			alphabet[i]=0;
		}
		return alphabet;
	}
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int number = sc.nextInt();
		String [] word = new String[number];
		for(int i=0;i<number;i++) {
			word[i] = sc.next();
		}
		int count = number;
		int []alphabet = new int[26];
		for(int i=0;i<word.length;i++) {
			int prev = 0;
			check(alphabet);
			for(int j=0;j<word[i].length();j++) {
				int now = word[i].charAt(j);
				if(prev != now) {
					if(alphabet[now-97]==0) {
						alphabet[now-97]=1;
						prev=now;
					}
					// 해당 문자가 이미 나온 적이 있는 경우
					else {
						count--;
						break;
					}
				}
				// 앞선 문자와 j번째 문자가 같다면 
				else {
					prev=now;
				}
			}
		}
		System.out.println(count);
		sc.close();
	}
}

파이썬을 공부하면서 파이썬으로 풀어보았다.

 

먼저 코드를 첨부하고 살펴보자.

 

(파이썬 코드)

alphabet = []
for index in range(26):
    alphabet.append(0)     # 길이가 26인 alphabet 리스트 값을 모두 0으로 초기화

number = int(input())
count = 0       # count는 0부터 시작
for word in range(number):    #  입력한 숫자만큼 
    word = input()   # 단어 입력
    no_count = False  # no_count 라는 변수를 우선 False 로 초기화 
    standard = word[0] # standard 라는 변수에는 단어의 첫 글자를 할당
    alphabet[ord(standard)-97] += 1  # alphabet[해당 알파벳을 가리키는 인덱스] = 1 (0만 아니면 된다.)
    for w in word[1:]: # standard (첫글자)를 가지고 w(두번째 글자)부터 문자열을 추적해보자. 
        if(standard == w):  # 두 알파벳이 연속되었으면 
            standard = w  # 우선 standard 를 해당 알파벳으로 바꿔주고 계속 추적해보자.
            continue
        elif(standard != w):  # 두 알파벳이 연속되지 않았다면(다르다면) 
            standard = w   # standard 를 해당 알파벳으로 바꿔주고 
            if(alphabet[ord(w)-97] == 0):  # 해당 알파벳이 처음 나온거라면 
                alphabet[ord(standard)-97] += 1
                continue
            else:  # 연속되지 않았는데, 전에 나온적이 있다면 
                no_count = True  # no_count = True 로 해주고 볼 것도 없이 그룹단어가 아니다.
                break
    alphabet = [0 for i in range(26)]  # 새로운 단어를 입력받기 전 alphabet 리스트 다시 0으로 초기화
    if(no_count == False):  # else문에 걸리지 않았다면(= 다 검사해도 문제 없었다면)
        count += 1   # count 1 증가 
print(count)

파이썬 코드는 이렇다.
그래도 코드를 구글링 하지 않고 풀었다. (아스키코드로 변환하는 방법은 잠깐 구글링했지만)

로직은 알파벳 개수만큼의 길이를 가진 alphabet[] 이라는 리스트를 생성해주고

a는 0번째 index
b는 1번째 index
..
..
z는 26번째 index

라고 생각한다.
모든 초기값을 0으로 설정해주고,
사용자에게 단어를 입력받고, 0번째에 위치한 단어를 standard 라는 변수에 담고
1번째부터 단어 끝까지 돌면서 그룹단어를 찾는다.
이 때, a = 97 ~ z= 122 라는 아스키코드를 가지고 있으므로
alphabet[ord(w)-97]는 a를 가리키는 위치라고 할 수 있다.
각 알파벳 위치를 1씩 증가시켜줌으로써 (1로 변환해도 상관없다,0만 아니면 된다.)
문자열중에 해당 문자가 나왔다는 것을 알 수 있다.

연속해서 나온 단어는 인정이지만,
연속하지 않고 떨어져서 중복하여 나온 단어는 else 문으로 빠져 바로 반복문을 종료하고
다음 단어를 사용자에게 입력받는다.

로직은 말로 설명할 수 있는데, 완벽한 코드로 구현하기에는 디버깅을 몇 번 하고서 알 수 있었다.
우선, 맨 처음에 틀렸던 이유는 새로운 단어를 입력 받기 전에 alphabet 리스트를 다시 모두 0으로 초기화 시키지 않아서였다.
그리고 break 문을 만나서 for문을 빠져나왔을 때, 처음엔 if(w==word[-1])로 했다가 틀렸다.
공교롭게 맨 마지막 단어가 앞서 나온 단어와 중복한 관계라면, if(w==word[-1])은 break 문을 만나서 탈출한 경우라도 count+=1 이 실행된다.

그래서 고친 코드가 no_count 라는 boolean 변수를 False로 초기에 설정해주고
else 문에 들어가기만 하면 break 문을 통해 탈출하는 동시에, 값을 True 로 바꿔준 코드였다.
그러면, 마지막 문자에서 break 문을 만나도 if(no_count == False)문이 수행되지 않기 때문이다.

반응형