예제를 처음 봤을 때 잠깐 멈췄다. 뒤집은 단어가 따로 없는 것처럼 보였기 때문이다. 조건을 다시 읽고 나서 회문이라는 걸 알았다.
문제 소개
단어 목록에서 비밀번호를 찾는 문제다. 조건은 하나다. 비밀번호를 뒤집은 문자열도 같은 목록에 있어야 한다. 비밀번호를 찾으면 길이와 가운데 글자를 출력한다. 모든 단어의 길이는 홀수로 보장된다.
| 항목 | 내용 |
|---|---|
| 입력 | 단어 수 N (2 ≤ N ≤ 100), 소문자 단어 N개 (길이 3~13, 홀수) |
| 출력 | 비밀번호 길이, 가운데 글자 (답은 유일) |
| 핵심 개념 | 문자열 뒤집기, 회문(palindrome), 리스트 탐색 |
| 난이도 | 브론즈 1 |
핵심 조건 분석
예제 2의 입력을 하나씩 확인해보면 이렇다.
| 단어 | 뒤집기 | 목록에 존재? |
|---|---|---|
kisik |
kisik |
✅ (자기 자신 = 회문) |
ptq |
qtp |
❌ |
tttrp |
prttt |
❌ |
tulipan |
napilut |
❌ |
kisik은 회문이라 뒤집어도 자기 자신이다. "뒤집은 문자열이 목록에 있어야 한다"는 조건을 자기 자신을 통해 만족한다. 회문은 별도로 처리할 필요 없다. 동일한 조건 검사로 자연스럽게 걸린다.
비밀번호 후보가 될 수 있는 경우는 두 가지로 정리된다.
| 경우 | 조건 | 예시 |
|---|---|---|
| 쌍으로 존재 | s[::-1]이 목록에 따로 있음 |
abc ↔ cba |
| 회문 | s == s[::-1] |
kisik, aba |
구현에서는 둘을 구분하지 않고 s[::-1] in word 하나로 처리한다.
풀이 접근
단어를 하나씩 보면서 뒤집은 문자열이 목록에 있는지 확인한다.
중요한 구조 결정이 하나 있다. 입력을 받으면서 동시에 탐색하면 아직 들어오지 않은 단어는 찾지 못한다.
# 입력 예시: 3 / abc / def / cba
# abc 읽는 시점 → cba 아직 없음 → 탐색 실패
# def 읽는 시점 → fed 없음
# cba 읽는 시점 → abc 이미 있음 ✅ → 정답 발견
그래서 입력을 전부 받은 뒤에 탐색한다. 입력 루프와 탐색 루프를 분리하는 게 핵심이다.
# 1단계 — 입력
for _ in range(n):
word.append(input())
# 2단계 — 탐색
for i in word:
if i[::-1] in word:
...
최종 코드
# 백준 9933 - 민균이의 비밀번호
# https://www.acmicpc.net/problem/9933
n = int(input())
word = []
for _ in range(n):
word.append(input())
for i in word:
revers = i[::-1]
if revers in word:
print(len(i), i[len(i)//2])
break
코드를 한 줄씩 보면
문자열 뒤집기 — i[::-1]
파이썬 슬라이싱은 text[start:end:step] 형태다. step을 -1로 주면 뒤에서 앞으로 이동하면서 문자열 전체를 뒤집는다.
"kisik"[::-1] # "kisik" ← 회문
"tulipan"[::-1] # "napilut"
"abc"[::-1] # "cba"
가운데 글자 — i[len(i)//2]
길이가 홀수이므로 가운데 인덱스는 항상 정확히 하나다. //는 정수 나눗셈이다.
| 단어 | 길이 | len // 2 | 가운데 글자 |
|---|---|---|---|
kisik |
5 | 2 | s |
abcba |
5 | 2 | c |
tulipan |
7 | 3 | i |
시간복잡도
| 단계 | 복잡도 | 이유 |
|---|---|---|
| 입력 저장 | O(N) | 단어 N개 순회 |
| 뒤집기 ([::-1]) | O(L) | 단어 길이 L만큼 복사 |
| 리스트 탐색 (in list) | O(N) | 최악 시 리스트 전체 순회 |
| 전체 | O(N²) | N ≤ 100이라 실질적 문제 없음 |
in list 대신 in set을 쓰면 탐색이 O(1)이 된다. 이 문제에서는 N이 최대 100이라 체감 차이가 없지만, 입력이 커지는 문제라면 set으로 바꾸는 게 맞다.
짚고 가는 실수들
구현하면서 문법 표현 쪽에서 여러 군데 틀렸다. 알고리즘보다 파이썬 표현 습관의 문제였다.
| 틀린 코드 | 올바른 코드 | 원인 |
|---|---|---|
n = input() |
n = int(input()) |
range()는 정수만 받음 |
for pwd in input(): |
word.append(input()) |
문자열을 글자 단위로 순회함 |
i[::-] |
i[::-1] |
step 값 누락 → SyntaxError |
w[len(i)//2] |
i[len(i)//2] |
선언하지 않은 변수 → NameError |
입력 루프 안에 탐색 루프 중첩 |
루프 분리 | break가 안쪽 루프만 종료함 |
특히 for pwd in input()은 조심할 부분이다. 파이썬에서 문자열은 이터러블이라 for에 바로 넣으면 글자 하나씩 꺼낸다. 단어 전체를 받을 때는 input()을 루프 없이 그대로 쓴다.
흐름 자체는 처음부터 맞게 잡았다. 코드로 옮길 때 파이썬 표현이 손에 덜 익은 게 드러났다. 개념을 아는 것과 그걸 코드로 표현하는 건 따로 연습해야 한다는 걸 다시 느꼈다.
🌿
'크래프톤 정글 > 정글에서 문제풀기' 카테고리의 다른 글
| [정글 알고리즘]-[하]-백준 10828 스택 (0) | 2026.03.16 |
|---|---|
| [정글 알고리즘]-[하]-백준 2164 카드2 (0) | 2026.03.16 |
| [정글 베이직 19] — 해시 테이블 · 성적 관리 (0) | 2026.03.13 |
| [정글 베이직 18] — 연결 리스트 (Linked List) (0) | 2026.03.13 |
| [정글 베이직 17] — 우선순위 큐 · 응급실 관리 (0) | 2026.03.13 |