[BOJ] 5525. IOIOI



풀이

주어진 문자열에 어떤 패턴의 부분 문자열이 몇개나 존재하는지 구하는 문제이다. KMP 알고리즘에 대해 새롭게 공부했다. 
처음에는 완전 탐색으로 구현했다. 당연하게도 시간초과가 발생했다.

= int(input())
= int(input())
= input()
def check(s,n):
    flag = True
    for i in range(n-1):
        if s[i]==s[i+1]:
            flag = False
            break
    return flag
 
len_s = len(s)
ans = 0
for i in range(len_s):
    if s[i]=='I' and len_s-i>=n*2+1:
        if check(s[i:i+(n*2)+1],n*2+1):
            ans+=1
print(ans)
cs

완전 탐색을 했을 경우의 시간 복잡도는 O(n*m) 으로 굉장히 크게 나온다. 하지만 KMP 알고리즘을 사용하면 O(m)으로 문제를 해결할 수 있다.

KMP 알고리즘
패턴 문자열에 대해 prefix와 suffix를 비교해 jump 할 수 있는 문자열 길이를 저장해 탐색을 빠르게 하는 알고리즘이다. 다른 블로그 글을 읽었는데 아무리 읽어도 이해가 안돼서 동빈나님의 유튜브 강의를 참고했다. 아직도 100% 이해는 되지 않는다.ㅠㅠ

= int(input())
= int(input())
= input()
 
def get_pi_table(m, s):
    pi = [0]*m
    j = 0
    for i in range(1,m):
        while j>0 and s[j]!=s[i]:
            j = pi[j-1]
        if s[j]==s[i]:
            pi[i] = j+1
            j+=1
    return pi
 
def KMP(s, m, pattern, pi):
    pattern_size = len(pattern)-1
    j = 0
    ans = 0
    for i in range(m):
        while j>0 and s[i]!=pattern[j]:
            j = pi[j-1]
        if s[i] == pattern[j]:
            if j == pattern_size:
                ans+=1
                j = pi[j]
            else:
                j+=1
    return ans
        
pattern = 'I'+'OI'*n
pi = get_pi_table(2*n+1,pattern)
print(KMP(s,m,pattern,pi))
cs

No comments:

Powered by Blogger.