[Java] 백준 2607 비슷한 단어

hyunnzl·2024년 12월 12일

백준

목록 보기
11/116
post-thumbnail

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

난이도

실버2

문제

영문 알파벳 대문자로 이루어진 두 단어가 다음의 두 가지 조건을 만족하면 같은 구성을 갖는다고 말한다.

두 개의 단어가 같은 종류의 문자로 이루어져 있다.
같은 문자는 같은 개수 만큼 있다.
예를 들어 "DOG"와 "GOD"은 둘 다 'D', 'G', 'O' 세 종류의 문자로 이루어져 있으며 양쪽 모두 'D', 'G', 'O' 가 하나씩 있으므로 이 둘은 같은 구성을 갖는다. 하지만 "GOD"과 "GOOD"의 경우 "GOD"에는 'O'가 하나, "GOOD"에는 'O'가 두 개 있으므로 이 둘은 다른 구성을 갖는다.

두 단어가 같은 구성을 갖는 경우, 또는 한 단어에서 한 문자를 더하거나, 빼거나, 하나의 문자를 다른 문자로 바꾸어 나머지 한 단어와 같은 구성을 갖게 되는 경우에 이들 두 단어를 서로 비슷한 단어라고 한다.

예를 들어 "DOG"와 "GOD"은 같은 구성을 가지므로 이 둘은 비슷한 단어이다. 또한 "GOD"에서 'O'를 하나 추가하면 "GOOD" 과 같은 구성을 갖게 되므로 이 둘 또한 비슷한 단어이다. 하지만 "DOG"에서 하나의 문자를 더하거나, 빼거나, 바꾸어도 "DOLL"과 같은 구성이 되지는 않으므로 "DOG"과 "DOLL"은 비슷한 단어가 아니다.

입력으로 여러 개의 서로 다른 단어가 주어질 때, 첫 번째 단어와 비슷한 단어가 모두 몇 개인지 찾아 출력하는 프로그램을 작성하시오.

입력

첫째 줄에는 단어의 개수가 주어지고 둘째 줄부터는 한 줄에 하나씩 단어가 주어진다. 모든 단어는 영문 알파벳 대문자로 이루어져 있다. 단어의 개수는 100개 이하이며, 각 단어의 길이는 10 이하이다.

출력

입력으로 주어진 첫 번째 단어와 비슷한 단어가 몇 개인지 첫째 줄에 출력한다.

내 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;

class Main {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int N = Integer.parseInt(br.readLine());
		String origin = br.readLine();

		HashMap<Character, Integer> hs = new HashMap<>();
		for (int i = 0; i < origin.length(); i++) {
			Character c = origin.charAt(i);
			hs.put(c, hs.getOrDefault(c, 0) + 1);
		}

		int ans = 0;
		for (int t = 0; t < N - 1; t++) {
			String str = br.readLine();
			
			if(Math.abs(origin.length() - str.length()) > 1) {
				continue;
			}
			
			HashMap<Character, Integer> hsTmp = new HashMap<>();
			for (int i = 0; i < str.length(); i++) {
				Character c = str.charAt(i);
				hsTmp.put(c, hsTmp.getOrDefault(c, 0) + 1);
			}
			
			if (isSimilar(hs, hsTmp)) {
                ans++;
            }
		}
		System.out.println(ans);
	}

	private static boolean isSimilar(HashMap<Character, Integer> hs, HashMap<Character, Integer> hsTmp) {
		int diff = 0;
		
		for(char c : hs.keySet()) {
			int cnt1 = hs.getOrDefault(c, 0);
			int cnt2 = hsTmp.getOrDefault(c, 0);
			diff += Math.abs(cnt1 - cnt2);
		}
		
		for(char c : hsTmp.keySet()) {
			if(!hs.containsKey(c)) {
				diff += hsTmp.get(c);
			}
		}
		
		return diff <= 2;
	}

}

3번이나 틀려버린 구현 문제...
예외처리 해줬다고 생각했는데도 계속 틀려서 아예 새로 작성했다.

일단 기준이 되는 문자열을 HashMap 으로 저장해뒀다.
그리고 반복문으로 비교를 해야하는 문자열을 하나씩 비교를 해야하는데,
두 문자열의 길이가 1 초과 라면 아예 다음 문자열로 넘어간다.

길이의 차이가 -1, 0, 1 이라면 비교를 해준다.
원본 문자열에 있는 문자들과 비교가 필요한 문자들을 각각 비교하여diff를 업데이트 한다.
비교가 필요한 문자열에는 있는데 원본 문자열에는 없는 것도 확인해준다.

diff의 총합이 2보다 작거나 같다면 유사한 문자열로 판별할 수 있다.


0개의 댓글