[알고리즘] LCS(Longest Common Subsequence)

2024. 10. 7. 19:52·공부/알고리즘
목차
  1. 참고 자료
  2. 🖐️[알고리즘] LCS(Longest Common Subsequence)
  3. ☑️ LCS 문제(LCS Problem)
  4. ☑️ LCS의 특성
  5. ☑️ LCS의 점화식 표현
  6. ☑️ LCS 문제 구현

 

참고 자료

  • Introduction to Algorihms (CLRS)
  • GeeksForGeeks : https://www.geeksforgeeks.org/longest-common-subsequence-dp-4/
  • SNU OPEN COURSEWARE : https://ocw.snu.ac.kr/sites/default/files/NOTE/Week 6_2.pdf
  • Carnegie Mellon Univ : https://www.cs.cmu.edu/~15451-s15/LectureNotes/lecture04.pdf
  • Claude AI ( 문법 확인용 )

🖐️[알고리즘] LCS(Longest Common Subsequence)

 

LCS는 공통 부분 수열 중에서 길이가 가장 긴 공통 부분 수열, 즉 최장 공통 부분 수열을 의미한다. 최장 공통 부분 수열과 공통 부분 수열, 부분 수열을 쉽게 이해하기 위해서 문자 집합을 생각해보자.

 

문자 집합 “ABC”가 있다고 가정하고 부분 수열을 살펴보자. 부분 수열은 일반적으로 길이가 N인 문자 집합은 2^n개의 부분 수열을 가진다.

 

문자 집합 “ABC”는 길이가 3이므로, 부분 수열은 다음과 같이 총 8개로 나타낼 수 있다.

  1. “”
  2. “A”
  3. “B”
  4. “C”
  5. “AB”
  6. “AC”
  7. “BC”
  8. “ABC”

 

공통된 부분 수열은 2개의 문자 집합에서 서로에게 공통된 부분들을 의미한다. 다음 아래의 문자 집합 2개를 보자.

 

두 문자 집합에서 각각 길이가 3과 4인 공통된 부분 수열을 1개씩 선정하면 다음과 같다.

 

또, 길이가 5 이상인 공통된 부분 수열은 없기 때문에 위의 <B,C,B,A>가 최장 공통 부분 수열, LCS가 된다. 단, 이때 LCS는 길이가 4인 공통 부분 수열을 의미하므로 추가적으로 존재 할 수 있다.

 


☑️ LCS 문제(LCS Problem)

두 Sequence가 존재할 때, 최대 길이의 LCS를 찾는 것이 목표다. LCS 문제는 DP 개념을 통해서 해결할 수 있다.

 


☑️ LCS의 특성


☑️ LCS의 점화식 표현

 


☑️ LCS 문제 구현

LCS 문제는 재귀 함수, 메모이제이션 사용, 상·하향식 DP(테이블)를 통해서 해결할 수 있다.

 

🟧 재귀 함수를 사용한 구현

def lcs(t1, t2,t1_len, t2_len):
    if t1_len == 0 or t2_len == 0:
        return 0
    elif t1[t1_len - 1] == t2[t2_len - 1]:
        return 1 + lcs(t1, t2, t1_len - 1, t2_len - 1)
    else:
        return max(lcs(t1, t2, t1_len - 1, t2_len), lcs(t1,t2,t1_len, t2_len-1))
        

if __name__ == "__main__":
    t1 = "ABCDEFG"
    t2 = "ADDADG"
    
    print(lcs(t1,t2, len(t1), len(t2)))

 

 

🟧 재귀 + 메모이제이션 사용한 구현

# Python implementation of Top-Down DP of LCS problem

# Returns length of LCS for S1[0..m-1], S2[0..n-1]
def lcs(S1, S2, m, n, memo):
    # Base Case
    if m == 0 or n == 0:
        return 0

    # Already exists in the memo table
    if memo[m][n] != -1:
        return memo[m][n]

    # Match
    if S1[m - 1] == S2[n - 1]:
        memo[m][n] = 1 + lcs(S1, S2, m - 1, n - 1, memo)
        return memo[m][n]

    # Do not match
    memo[m][n] = max(lcs(S1, S2, m, n - 1, memo),
                     lcs(S1, S2, m - 1, n, memo))
    return memo[m][n]

if __name__ == "__main__":
    S1 = "AGGTAB"
    S2 = "GXTXAYB"

    m = len(S1)
    n = len(S2)
    memo = [[-1 for _ in range(n + 1)] for _ in range(m + 1)]
    print("Length of LCS is", lcs(S1, S2, m, n, memo))

 

🟧 Bottom-Up 접근 구현

def get_lcs_length(S1, S2):
    m = len(S1)
    n = len(S2)

		# DP Table 공간 초기화 -> 0
    dp = [[0] * (n + 1) for x in range(m + 1)]

    # 상향식 접근으로 작은 문제부터 하나하나 풀어나간다.
    # "ABCD"와 "BJED"의 LCS를 찾아가는 과정은 다음과 같다.
    # "A"와 "B"의 LCS 찾기
    # "A"와 "BJ"의 LCS 찾기
    # "A"와 "BJE"의 LCS 찾기
    # ...
    # "ABCD"와 "BJED"의 LCS 찾기
    for i in range(1, m + 1):
        for j in range(1, n + 1):
		        # 문자열이 일치할 경우, 현재 DP Table에 이전 값 + 1을 추가
            if S1[i - 1] == S2[j - 1]:
                dp[i][j] = dp[i - 1][j - 1] + 1
            else:
            # 문자열이 일치하지 않을 경우, 이전 LCS 중 가장 큰 값을 추가
                dp[i][j] = max(dp[i - 1][j],
                               dp[i][j - 1])
    return dp[m][n]


if __name__ == "__main__":
    S1 = "AGGTAB"
    S2 = "GXTXAYB"
    print("Length of LCS is", get_lcs_length(S1, S2))

'공부 > 알고리즘' 카테고리의 다른 글

[알고리즘] C++로 이해하는 DFS와 BFS  (0) 2025.04.03
[알고리즘] 위상정렬(Topology Sort)  (1) 2024.10.11
[알고리즘] 백트래킹(Backtracking)  (1) 2024.09.14
[알고리즘] 재귀란 무엇인가?  (2) 2024.09.14
[알고리즘] #1. A* 알고리즘을 알아보자  (2) 2024.06.14
  1. 참고 자료
  2. 🖐️[알고리즘] LCS(Longest Common Subsequence)
  3. ☑️ LCS 문제(LCS Problem)
  4. ☑️ LCS의 특성
  5. ☑️ LCS의 점화식 표현
  6. ☑️ LCS 문제 구현
'공부/알고리즘' 카테고리의 다른 글
  • [알고리즘] C++로 이해하는 DFS와 BFS
  • [알고리즘] 위상정렬(Topology Sort)
  • [알고리즘] 백트래킹(Backtracking)
  • [알고리즘] 재귀란 무엇인가?
태역
태역
  • 태역
    RYULAB
    태역
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 언어
        • C
        • C++
        • C#
      • 엔진, 프레임워크
        • Unity
        • Unreal
        • Electron
      • 공부
        • 디자인 패턴
        • 수학
        • CS
        • Git
        • 알고리즘
        • 자료구조
      • 코테
        • 프로그래머스
        • 백준
      • 독서
        • Effective C#
        • CLR via C#
        • 뇌를 자극하는 윈도우즈 시스템 프로그래밍
        • 오브젝트
        • CSAPP
        • OSTEP
      • 프로젝트
        • Unity
      • 개발 일지
        • 퓨처리티
        • 골든타임
      • 활동
        • 게임잼 후기
        • 게임제작동아리 브릿지
        • 크래프톤 정글
        • 기타
      • 기타
  • 블로그 메뉴

    • 링크

    • 공지사항

      • 2024 04 17
    • 인기 글

    • 태그

      인프런 #인프런강의후기 #게임개발 #게임개발강의 #인강후기 #강의후기 #게임개발자 #인프런강의
      오블완
      티스토리챌린지
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    태역
    [알고리즘] LCS(Longest Common Subsequence)
    상단으로

    티스토리툴바

    단축키

    내 블로그

    내 블로그 - 관리자 홈 전환
    Q
    Q
    새 글 쓰기
    W
    W

    블로그 게시글

    글 수정 (권한 있는 경우)
    E
    E
    댓글 영역으로 이동
    C
    C

    모든 영역

    이 페이지의 URL 복사
    S
    S
    맨 위로 이동
    T
    T
    티스토리 홈 이동
    H
    H
    단축키 안내
    Shift + /
    ⇧ + /

    * 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.