알고리즘 문제(SOL)

[백준/2607/파이썬] 비슷한 단어

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

 

2607번: 비슷한 단어

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

www.acmicpc.net

Problem

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

조건

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

  • 두 개의 단어가 같은 종류의 문자로 이루어져 있다.
  • 같은 문자는 같은 개수 만큼 있다.
  • 예를 들어 "DOG"와 "GOD"은 둘 다 'D', 'G', 'O' 세 종류의 문자로 이루어져 있으며 양쪽 모두 'D', 'G', 'O' 가 하나씩 있으므로 이 둘은 같은 구성을 갖는다. 하지만 "GOD"과 "GOOD"의 경우 "GOD"에는 'O'가 하나, "GOOD"에는 'O'가 두 개 있으므로 이 둘은 다른 구성을 갖는다.
  • 두 단어가 같은 구성을 갖는 경우, 또는 한 단어에서 한 문자를 더하거나, 빼거나, 하나의 문자를 다른 문자로 바꾸어 나머지 한 단어와 같은 구성을 갖게 되는 경우에 이들 두 단어를 서로 비슷한 단어라고 한다.

SOL

비교 기준: 첫번째 단어

첫번째 단어: Dictionary 형태로 저장을 하게되면, 단어의 구성과 각 단어의 갯수를 알 수 있다.

반복문을 돌면서, Dictionary 형태로 저장되어있는 부분을 비교할거임. 만약 ,같으면 -1씩 해줄거임. 그리고, 구성하지 않는 단어가 있다면, 절대로 나오지 않을 수를 해당 key의 value에 넣어줄거다.

 

이제 조건에 맞게 if/else문을 적절하게 분기점으로 잘 나누어서 구현하면 된다. 생각보다, if/else문이 많아지면 복잡해지므로, 주석을 달거나, 순서도를 그리거나, 어떤 방법이든 정리를 하면, 실수가 많이 줄어든다.

저는 주로 사과패드에서 순서도를 그리거나, 주석을 많이 다는 편입니다. (사실, 주석은 많이 달지 않는게 좋다고하는데)

 

import sys
import copy
input = sys.stdin.readline

N = int(input())

words =[input().rstrip() for _ in range(N)]
#비교하는 기준
word={}
ans=0
for w in words[0]:
    if w in word:
        word[w] +=1
    else:
        word[w] =1
        

for i in range(1,N):
    # 비교할 필요가 없는 경우 길이가 다른 경우
    if (len(words[i]) > len(words[0])+1) or (len(words[i]) < len(words[0]) -1):
        continue
    chk_word = copy.deepcopy(word)
    for w in words[i]:
        # 기준 단어에, 단어가 있다면, -=1
        if w in chk_word:
            chk_word[w] -=1
        else:
        #1글자 바뀌는거 까진 허용
            chk_word[w] = 1000
    # 변화한 거를 기록. 
    change =[0,0,0]
    flag =True
    
    for chk in chk_word:
        # 같은 구성을 가지는 경우
        if chk_word[chk]==0:
            continue
        # 1글자가 적은 경우
        if chk_word[chk]==1:
            change[1] +=1
        # 1글자가 많은 경우,
        elif chk_word[chk] == -1:
            change[0] +=1
        #1글자가 다른 경우
        elif chk_word[chk] == 1000:
            change[2] +=1
        else:
            flag= False
            break
    if sum(change)>2:
        flag=False
    elif change[0] >2 or change[1] >2 or change[2]>2:
        flag = False
    
    if flag:
        ans+=1 
print(ans)