라떼군 이야기


12 / 16강

문자열에서 패턴 찾기

문서에서 단어를 찾으려면 패턴이 연속으로 등장하는 위치를 찾아야 합니다. 8강의 LCS처럼 중간 글자를 건너뛰어서는 안 됩니다.

가장 단순한 방법

패턴을 놓을 수 있는 시작 위치를 하나씩 고르고, 글자를 앞에서부터 비교합니다.

def find_pattern(text, pattern):
    if not pattern:
        return 0
    for start in range(len(text) - len(pattern) + 1):
        matched = True
        for offset in range(len(pattern)):
            if text[start + offset] != pattern[offset]:
                matched = False
                break
        if matched:
            return start
    return -1

print(find_pattern("ababc", "abc"))

출력은 2입니다. 인덱스는 0부터 셉니다. 빈 패턴은 0번 위치에서 찾은 것으로 정했습니다. 패턴이 본문보다 길면 후보 위치가 없어 -1을 반환합니다.

본문 길이가 n, 패턴 길이가 m일 때, 시작 위치마다 최대 m글자를 비교하므로 최악의 시간은 O(nm)입니다. aaaaab에서 aaab를 찾을 때처럼 비슷한 부분을 반복해서 읽을 수 있습니다.

KMP는 실패한 비교도 활용합니다

KMP는 패턴의 앞부분과 뒷부분이 얼마나 겹치는지 미리 기록합니다. 예를 들어 abab는 앞의 ab와 뒤의 ab가 같습니다. abab까지 맞춘 뒤 실패했다면, 이미 맞았던 끝의 ab를 다음 후보의 시작으로 활용할 수 있습니다.

이 겹침 정보로 본문 위치를 뒤로 돌리지 않고 비교를 이어갑니다. 패턴 준비에 O(m), 본문 탐색에 O(n)이 들어 전체 O(n+m)입니다. 어디로 돌아갈지를 기록한 표를 잘 만드는 것이 핵심입니다.

다른 방법도 전제를 봅니다

확인 문제

본문 aaaa에서 패턴 aa가 나타나는 위치를 모두 구하면 몇 개인가요? 찾은 뒤 패턴 길이만큼 건너뛰어도 될까요?

해설 보기

0, 1, 2번의 세 곳입니다. 등장 위치가 겹칠 수 있습니다. 무조건 두 칸씩 건너뛰면 1번을 놓칩니다. 첫 번째만 찾는 문제와 모든 등장 위치를 찾는 문제의 조건을 구분해야 합니다.

제품 개발 파트너나 강의를 찾으시나요? 개인, 팀, 기업 모두 환영합니다. 문제 정의부터 출시까지 함께하며, 팀과 학교에 맞춘 개발 강의도 합니다.