알고리즘
백준[Python] - 5525 : IOIOI
BKM
2024. 3. 23. 00:29
문제
제한 사항 및 예제
풀이
풀이 1(시간 초과)
처음 접근시에는 리스트 슬라이싱을 활용해 $P_N$과 일치하는 부분을 찾으면 count를 올리는 식으로 구현하였다.
# IOIOI
n = int(input())
m = int(input())
s = input()
# p = ('O').join(['I']*(n+1))
# p와 일치하는지 확인
cnt=0
for i,v in enumerate(s):
if v=='I':
if i+(2*n+1)<m:
if s[i:i+(2*n+1)]==p:
cnt+=1
print(cnt)
하지만 $m=1,000,000$이고 IOIOIO...의 식으로 계속 반복되는 경우라고 하면, 슬라이싱을 사용해야하는 횟수가 500,000-1=499,999이므로 n이 21만 되어도 천만의 연산 횟수를 넘는다.
그러므로, 슬라이싱을 최소화 하는 방법을 적용해야 한다.
풀이 2(성공)
문자가 규칙에 맞게 배열되는 동안 수를 1씩 올려나가면 다음과 같은 배열이 만들어진다.
OOIOIOIOIIOII -> 0012345671231
그리고 이 중에서 $P_N$의 길이와 같은 $2N+1$보다 크거나 같고, 홀수인 경우를 선택하면 조건에 만족하는 부분이 선택된다.
# IOIOI
n = int(input())
m = int(input())
s = input()
# 슬라이싱 없이
cnt_lst = [0]*m
for i,v in enumerate(s):
if v=='I':
if cnt_lst[i-1]:
if s[i-1]=='O':
cnt_lst[i]=cnt_lst[i-1]+1
else:
cnt_lst[i]=1
else:
cnt_lst[i]=1
else:
if cnt_lst[i-1]:
if s[i-1]=='I':
cnt_lst[i]=cnt_lst[i-1]+1
for i in cnt_lst:
if (i>=2*n+1)&(i%2==1):
cnt+=1
print(cnt)
다른 풀이
IOI의 단위로 count를 올려서 N만큼 count가 되면 결과값을 하나씩 올리고, count를 하나 줄이고 다시 탐색을 반복해 나가는 알고리즘이다.
나의 풀이와 방식은 조금 다르지만, 비슷한 원리로 해결하는 것 같다.
N = int(input())
M = int(input())
S = input()
cursor, count, result = 0, 0, 0
while cursor < (M - 1):
if S[cursor:cursor + 3] == 'IOI': #3칸
count += 1
cursor += 2
if count == N:
result += 1
count -= 1
else:
cursor += 1
count = 0
print(result)