최장 공통 부분 수열

AI
qwen-3-235b-a22b-instruct-2507
작성자
익명
작성일
2025.09.13
조회수
None
버전
v1

최장 공통 부분 수열

개요

최장통 부분 수열(Longest Subsequence, 이하 LCS)은 개 이상의 문자열(또는 수열)에서 동시에 나타나는 부분 수열(subsequence) 중 가장 긴 것을 찾는 문제입니다. 이 알고리즘은 자연어처리(NLP), 생물정보학, 버전 관리 시스템(예: [git diff](/doc/%EA%B8%B0%EC%88%A0/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4/%EB%B2%84%EC%A0%84%EA%B4%80%EB%A6%AC/git%20diff)), 텍스트 비교 도구 등 다양한 분야에서 핵심적으로 활용됩니다.

부분 수열이란 원래 수열에서 일부 요소를 삭제하여 얻을 수 있는 새로운 수열을 의미하며, 요소의 순서는 유지되어야 하지만, 연속적일 필요는 없습니다. 예를 들어, 수열 ABCBDAB의 부분 수열에는 ABD, BCB, ABBA 등이 포함될 수 있습니다.

LCS는 문자열 간의 유사도를 측정하는 데 유용하며, 특히 자연어처리에서는 문서 간 유사성 분석, 기계 번역 평가, 오타 수정, 문장 정렬 등에 응용됩니다.


알고리즘 원리

1. 문제 정의

두 수열 X = x₁, x₂, ..., xₘY = y₁, y₂, ..., yₙ이 주어졌을 때, X와 Y의 공통 부분 수열 중 길이가 가장 긴 것을 찾는 것이 목표입니다.

예: - X = "AGCAT" - Y = "GACAT" - 가능한 공통 부분 수열: "ACAT", "GAT", "GCAT" 등 - 최장 공통 부분 수열: "GAT" 또는 "ACAT" (길이 4)

2. 동적 프로그래밍 접근

LCS 문제는 동적 프로그래밍(Dynamic Programming, DP)을 통해 효율적으로 해결할 수 있습니다. 이 방법은 중복된 하위 문제를 저장하고 재사용함으로써 시간 복잡도를 줄입니다.

점화식 (Recurrence Relation)

L[i][j]X의 첫 i개 문자와 Y의 첫 j개 문자의 LCS 길이라고 정의합니다.

  • L[0][j] = 0 (X가 빈 문자열)
  • L[i][0] = 0 (Y가 빈 문자열)
  • 만약 X[i-1] == Y[j-1], 즉 마지막 문자가 같으면:
  • L[i][j] = L[i-1][j-1] + 1
  • 그렇지 않으면:
  • L[i][j] = max(L[i-1][j], L[i][j-1])

이 점화식을 바탕으로 m×n 크기의 2차원 테이블을 채워 나갑니다.

예시 계산

X = "ABCD", Y = "ACBD"

Ø A C B D
Ø 0 0 0 0 0
A 0 1 1 1 1
B 0 1 1 2 2
C 0 1 2 2 2
D 0 1 2 2 3

최종 값 L[4][4] = 3이며, 실제 LCS는 "ABD" 또는 "ACD"입니다.


알고리즘 구현

다음은 Python을 사용한 LCS 길이 계산 및 실제 수열 복원 예시입니다:

def lcs_length_and_sequence(X, Y):
    m, n = len(X), len(Y)
    # DP 테이블 초기화
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    
    # 테이블 채우기
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if X[i-1] == Y[j-1]:
                dp[i][j] = dp[i-1][j-1] + 1
            else:
                dp[i][j] = max(dp[i-1][j], dp[i][j-1])
    
    # LCS 수열 복원
    lcs = []
    i, j = m, n
    while i > 0 and j > 0:
        if X[i-1] == Y[j-1]:
            lcs.append(X[i-1])
            i -= 1
            j -= 1
        elif dp[i-1][j] > dp[i][j-1]:
            i -= 1
        else:
            j -= 1
    
    return dp[m][n], ''.join(reversed(lcs))

# 사용 예
X = "AGCAT"
Y = "GACAT"
length, sequence = lcs_length_and_sequence(X, Y)
print(f"LCS 길이: {length}, 수열: {sequence}")  # 출력: LCS 길이: 4, 수열: ACAT


시간 및 공간 복잡도

항목
시간 복잡도 O(m × n)
공간 복잡도 O(m × n)

단, 공간 최적화를 위해 두 줄만 유지하는 방식으로 공간 복잡도를 O(min(m, n))로 줄일 수 있습니다. 다만 이 경우 실제 수열 복원은 불가능하거나 추가 처리가 필요합니다.


응용 분야

1. 자연어처리 (NLP)

  • 문서 유사도 측정: 두 문장 또는 문서의 LCS를 통해 구조적 유사성을 분석합니다.
  • 오타 감지 및 수정: 입력 문장과 정답 문장을 비교해 차이를 식별합니다.
  • 기계 번역 평가: 예측 문장과 참조 문장의 LCS를 기반으로 정확도를 계산합니다.

2. 버전 제어 시스템

  • git diffdiff 명령어는 LCS 알고리즘을 기반으로 파일 간 변경 사항을 비교합니다.
  • 추가/삭제된 부분을 추적하기 위해 LCS의 보완 알고리즘인 Myers diff 알고리즘이 사용됩니다.

3. 생물정보학

  • DNA 또는 단백질 서열 정렬에 활용됩니다.
  • 유사한 유전자 서열을 찾는 데 중요한 기초 기술입니다.

관련 알고리즘 및 확장

  • 최장 공통 부분 문자열(Longest Common Substring): 부분 수열이 아닌 연속된 부분 문자열을 찾는 문제입니다. DP 접근법이 유사하지만 조건이 다릅니다.
  • 편집 거리(Edit Distance): 삽입, 삭제, 치환을 통해 한 문자열을 다른 문자열로 변환하는 최소 연산 횟수. LCS와 밀접한 관련이 있으며, 편집 거리 = m + n - 2 × LCS로 근사 가능합니다.
  • Hirschberg’s 알고리즘: 공간 복잡도 O(min(m, n))를 유지하면서 실제 LCS 수열을 복원할 수 있는 분할 정복 기반 알고리즘입니다.

참고 자료

  • Cormen, T. H., Leiserson, C. E., Rivest, R. L., & Stein, C. (209). Introduction to Algorithms (3rd ed.). MIT Press.
  • Gusfield, D. (1997). Algorithms on Strings, Trees, and Sequences: Computer Science and Computational Biology. Cambridge University Press.
  • Myers, E. W. (1986). "An O(ND) Difference Algorithm and Its Variations". Algorithmica.

관련 문서

LCS는 단순해 보이지만, 실세계 응용에서 중요한 기초 알고리즘으로, 자연어처리 기술의 정교한 분석을 가능하게 합니다.

AI 생성 콘텐츠 안내

이 문서는 AI 모델(qwen-3-235b-a22b-instruct-2507)에 의해 생성된 콘텐츠입니다.

주의사항: AI가 생성한 내용은 부정확하거나 편향된 정보를 포함할 수 있습니다. 중요한 결정을 내리기 전에 반드시 신뢰할 수 있는 출처를 통해 정보를 확인하시기 바랍니다.

이 AI 생성 콘텐츠가 도움이 되었나요?