728x90
반응형
골드 Ⅴ
https://www.acmicpc.net/problem/20437
📄 문제
- 알파벳 소문자로 이루어진 문자열 W가 주어진다.
- 양의 정수 K가 주어진다.
- 어떤 문자를 정확히 K개를 포함하는 가장 짧은 연속 문자열의 길이를 구한다.
- 어떤 문자를 정확히 K개를 포함하고, 문자열의 첫 번째와 마지막 글자가 해당 문자로 같은 가장 긴 연속 문자열의 길이를 구한다.
위와 같은 방식으로 게임을 T회 진행한다.
💡 아이디어
- 연속된 문자열의 첫 번째와 마지막 글자가 같고 문자열에 해당 글자가 k개 존재해야 한다.
- 완전 탐색으로 문제를 풀이하면 문자열 게임의 수 T는 1 ≤ T ≤ 100이고 문자열 W와 정수 K가 1 ≤ K ≤ |W| ≤ 10,000 이므로 시간초과가 발생한다.
- 따라서, 딕셔너리를 활용하여 문제를 해결할 수 있다.
- 딕셔너리에 각 문자를 key 값으로 각 문자의 위치를 value 값으로 저장한다.
- 딕셔너리에 저장된 각 문자열의 위치에 따라 최대 길이와 최소 길이를 구한다.
- 각 문자가 k개 이상 존재해야 되기 때문에 각 문자열에 저장된 위치가 k개 이상인 문자만 길이 구하는 연산을 수행한다.
- 딕셔너리에 위치값이 순서대로 저장되어 있으므로 k개 이상의 위치를 갖고 있다면 k 개씩 순차적으로 길이 값을 구한다.
- k개로 구분한 위치의 처음 값과 마지막 값을 활용하여 문자열의 길이를 구한다. (길이 = 마지막 위치 - 처음 위치 + 1)
- 이때의 길이를 최댓값, 최솟값과 비교하여 갱신한다.
🟩 첫 번째 아이디어 (완전 탐색) - 시간 초과
- 이중 for문을 활용한다.
- 첫 번째 for문에서 탐색을 시작할 위치(i)를 정한다.
- 두 번째 for문에서는 첫 번째 for문에서 정한 위치 이후부터 탐색한다. (j)
- 두 번째 for문을 탐색하면서 시작 문자와 같은 문자가 등장하면 개수를 세어준다. (cnt += 1)
- 시작 문자와 같은 문자일 때, cnt == k가 되면 문자열 길이를 구한다.
- 최대, 최소 값을 비교하여 갱신해 준다
✅ 두 번째 아이디어 (딕셔너리 활용) - 최종코드
- 딕셔너리를 활용하여 문제를 풀이한다.
- 딕셔너리에 각 문자를 key 값으로 각 문자의 위치를 value 값으로 저장한다.
- 각 문자가 k개 이상 존재해야 되기 때문에 각 문자열에 저장된 문자의 위치가 k개 이상이면,
- 딕셔너리에 저장된 각 문자열의 위치에 따라 k개 씩 구분하여 길이를 구한다.
- 최대 길이와 최소 길이를 갱신한다.
📝 문제 풀이 (Code)
최종 코드 - 딕셔너리 활용
import sys
input = sys.stdin.readline
t = int(input())
for _ in range(t):
w = input()
k = int(input())
# 각 단어의 위치 저장
posi_dic = {}
for i in range(len(w)):
if posi_dic.get(w[i]):
posi_dic[w[i]].append(i)
else:
posi_dic[w[i]] = [i]
minV = 20001
maxV = 0
# 위치 배열로 최대, 최소 길이 찾기
for value in posi_dic.values():
n = len(value)
# 해당 문자 K개 이상을 가지고 있으면 길이 찾기
if n >= k:
for s in range(n-k+1):
cnt = value[s+k-1]-value[s]+1
if minV > cnt:
minV = cnt
if maxV < cnt:
maxV = cnt
if maxV:
print(minV, maxV)
else:
print(-1)
처음 코드 - 완전 탐색 (시간 초과)
더보기
t = int(input())
for _ in range(t):
w = input()
k = int(input())
n = len(w)
# 최댓값, 최솟값 저장
minV = 20001
maxV = 0
# 문자열이 k 개 이상이어야 하므로 n-k까지 탐색한다.
for i in range(n-k+1):
# 같이 문자열이 몇 개인지 저장
cnt = 1
# i 이후 문자부터 탐색
for j in range(i+1, n):
# 같은 문자면 cnt += 1
if w[i] == w[j]:
cnt += 1
# 처음 문자와 같은 문자가 k개 포함되면 i번째 문자 탐색 종료
# 최대, 최소 갱신
if cnt == k:
minV = min(minV, j - i + 1)
maxV = max(maxV, j - i + 1)
break
if maxV:
print(minV, maxV)
else:
print(-1)
728x90
반응형
'Algorithm Solving > Baekjoon' 카테고리의 다른 글
[백준] 12100 2048 (Easy) (파이썬) (0) | 2023.09.06 |
---|---|
[백준] 2668 숫자고르기 (파이썬) (0) | 2023.09.05 |
[백준] 12015 가장 긴 증가하는 부분 수열 2 (파이썬) (0) | 2023.08.31 |
[백준] 2470 두 용액 (파이썬) (0) | 2023.08.30 |
[백준] 2146 다리 만들기 (파이썬) (0) | 2023.08.29 |