최장 공통 부분 수열
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
최장 공통 부분 수열(LCS)은 하나 이상의 수열에서 공통으로 나타나는 가장 긴 부분 수열을 찾는 문제이다. 일반적인 경우, 임의 개수의 수열에 대한 LCS 문제는 NP-난해 문제로 효율적인 알고리즘이 존재하지 않을 가능성이 높지만, 수열 개수가 정해져 있다면 동적 계획법을 통해 다항 시간 내에 해결할 수 있다. 두 수열의 LCS는 동적 계획법으로 O(n × m)의 시간 복잡도로 해결 가능하며, LCS는 최적 부분 구조와 중복되는 하위 문제를 가지므로 동적 계획법 접근 방식에 적합하다. LCS는 유일하지 않을 수 있으며, LCS를 구하는 과정은 접두사, LCS 함수의 정의, 예시 등을 통해 재귀적으로 설명된다. LCS 알고리즘은 실제 적용을 위해 다양한 최적화 기법을 사용할 수 있으며, 무작위 문자열에서의 LCS 길이는 츠바탈-산코프 상수로 알려진 비례 상수에 의해 결정된다.
더 읽어볼만한 페이지
- 동적 계획법 - 배낭 문제
배낭 문제는 주어진 배낭 용량 내에서 물건들의 가치 합을 최대화하는 조합 최적화 문제로, 물건을 쪼갤 수 있는지, 개수 제한이 있는지에 따라 다양한 변형이 있으며, 동적 계획법, 탐욕 알고리즘 등으로 해결하고, NP-완전 문제에 속하며 자원 할당 문제 등에 응용된다. - 동적 계획법 - 차원의 저주
차원의 저주는 고차원 공간에서 데이터 분석 및 모델링의 어려움을 나타내는 현상으로, 계산 시간 증가, 수치 오차 발생, 조합 폭발 등의 문제점을 야기한다. - NP-완전 문제 - 지뢰 찾기
지뢰 찾기는 격자 형태 지뢰밭에서 지뢰를 피해 안전한 칸을 모두 여는 퍼즐 비디오 게임으로, 칸을 열어 지뢰 유무를 확인하며, 윈도우 탑재를 통해 대중화되었고 NP-완전 문제로 분류된다. - NP-완전 문제 - 스도쿠
스도쿠는 9x9 칸에 1부터 9까지의 숫자를 채워 넣는 퍼즐로, 각 가로줄, 세로줄, 3x3 칸에 숫자가 중복 없이 들어가야 하며, 레온하르트 오일러의 라틴 방진을 기반으로 다양한 변형과 응용 연구가 진행되고 있다. - 수열 - 코시 열
코시 열은 무한수열에서 항들이 뒤로 갈수록 서로 가까워지는 수열로, 수렴열은 항상 코시 열이지만 그 역은 성립하지 않을 수 있으며, 실수의 완비성 정의 및 무한급수 수렴성 판정에 중요한 역할을 하는 개념이다. - 수열 - 실베스터 수열
실베스터 수열은 각 항이 이전 항들의 곱에 1을 더한 값으로 정의되는 정수 수열로서, 재귀적으로 정의되며 이중 지수 함수적으로 증가하고, 이집트 분수 및 탐욕 알고리즘과 관련이 있으며, 역수 합은 1로 수렴한다.
최장 공통 부분 수열 | |
---|---|
개요 | |
문제 유형 | 알고리즘 문제 |
목표 | 두 개의 시퀀스에서 가장 긴 공통 부분 수열을 찾는 것 |
활용 분야 | 데이터 비교 파일 비교 생물정보학 |
복잡도 | 시간 복잡도 O(m*n), 공간 복잡도 O(min(m,n)) 또는 O(m*n) |
정의 | |
입력 | 두 개의 시퀀스 X와 Y |
출력 | X와 Y의 가장 긴 공통 부분 수열 (Longest Common Subsequence, LCS) |
부분 수열 | 주어진 시퀀스에서 일부 요소를 제거하여 얻을 수 있는 수열 (반드시 연속적일 필요는 없음) |
예시 | |
시퀀스 1 | AGGTAB |
시퀀스 2 | GXTXAYB |
LCS | "GTAB" (길이: 4) |
알고리즘 | |
동적 프로그래밍 | LCS 문제를 해결하기 위한 효율적인 방법 부분 문제의 최적 해를 저장하여 중복 계산을 피함 |
재귀적 관계 | X의 마지막 요소와 Y의 마지막 요소가 같으면, LCS(X, Y) = LCS(X-1, Y-1) + 1 다르면, LCS(X, Y) = max(LCS(X-1, Y), LCS(X, Y-1)) |
구현 | |
프로그래밍 언어 | 다양한 프로그래밍 언어로 구현 가능 (예: Python, C++, Java) |
최적화 | 공간 복잡도 최적화: O(min(m,n))까지 가능 비트 연산을 사용한 속도 향상 |
관련 문제 | |
최장 공통 부분 문자열 문제 | (Longest Common Substring Problem): 연속적인 부분 문자열을 찾는 문제 |
편집 거리 | (Edit Distance): 한 시퀀스를 다른 시퀀스로 변환하는 데 필요한 최소 연산 횟수를 찾는 문제 |
2. 복잡도
일반적으로, 임의의 수의 수열에 대한 LCS 문제는 NP-난해로 알려져 있다.[21] 즉, 효율적인 (다항 시간) 알고리즘이 존재하지 않을 가능성이 높다. 하지만 주어진 수열의 개수가 일정할 때는 동적 계획법을 사용하여 다항 시간 안에 문제를 해결할 수 있다.
LCS 문제는 최적 부분 구조를 갖는다. 즉, 문제를 더 작고 간단한 하위 문제로 분해할 수 있으며, 이는 다시 더 간단한 하위 문제로 분해될 수 있고, 결국 해답이 자명해진다. 특히 LCS는 중복되는 하위 문제를 가지는데, 상위 수준의 하위 문제에 대한 해답은 종종 하위 수준의 하위 문제에 대한 해답을 재사용한다. 이러한 두 가지 속성을 가진 문제는 동적 계획법 접근 방식에 적합하며, 여기서 하위 문제의 해답은 메모이제이션된다. 즉, 하위 문제의 해답이 재사용을 위해 저장된다.[23]
두 수열의 LCS 문제는 동적 계획법을 통해 효율적으로 해결할 수 있으며, 이 경우 시간 복잡도는 O(''n'' × ''m'')이다. (''n''과 ''m''은 각 수열의 길이)[2] 임의의 개수의 입력 수열에 대한 동적 계획법 해법은 ${\displaystyle O\left(N\prod _{i=1}^{N}n_{i}\right)}$의 시간 복잡도를 가진다.
복잡도를 더 낮출 수 있는 방법도 존재하며,[22] 이러한 방법들은 최장 공통 부분 수열의 길이, 수열을 이루는 알파벳의 크기 등에 영향을 받는다.
LCS는 유일하지 않을 수 있다. 예를 들어 "ABC"와 "ACB"의 LCS는 "AB"와 "AC" 둘 다이다.
3. 두 개의 수열에 대한 해
두 수열 과 이 주어졌을 때, LCS는 이 문제를 더 작은 부분 문제로 나누어 해결하고, 부분 문제의 해답을 표(메모이제이션)에 저장하여 상위 단계의 부분 문제에서 재사용하는 방식으로 구한다.
3. 1. 접두사
어떤 수열의 접두사는 말단이 잘려나간 수열이다. 예를 들어 S를 수열 (AGCA)라 할 때, (AG)는 S의 접두사 중 하나이다. 접두사는 "원래 배열의 이름" 뒤에, "접두사가 몇 개의 문자를 포함하는지"를 나타내는 첨자를 붙여서 나타낸다.[23] 접두사 (AG)는 S의 처음 두 요소를 포함하므로, S2로 표기한다. S의 가능한 접두사는 다음과 같다.[5]
:''S''1 = (A)
:''S''2 = (AG)
:''S''3 = (AGC)
:''S''4 = (AGCA)
3. 2. LCS 함수의 정의
LCS영어 함수는 두 수열 X와 Y에 대해 다음과 같이 재귀적으로 정의된다.
두 수열이 같은 원소로 끝난다고 가정하면, LCS영어를 찾기 위해 마지막 원소를 지우고 수열의 길이를 줄인다. 짧아진 수열에 대한 LCS영어를 찾은 후 삭제한 원소를 다시 붙인다.
예를 들어, (BANANA)와 (ATANA)처럼 같은 마지막 원소를 가진 두 수열이 있다. 마지막 원소를 삭제하는 과정을, 공통된 마지막 원소가 없을 때까지 반복한다. 삭제된 수열은 ANA이다. 이제 연산해야 하는 수열은 (BAN)와 (AT)이다. 이 두 수열의 LCS영어는 (A)이다. 삭제했던 부분수열 (ANA)를 다시 결합하면 (AANA)가 되고, 이것이 원 수열의 LCS영어가 된다.
접두사에 대해,
: ''LCS''(''Xn'', ''Ym'') = (''LCS''( ''Xn-1, ''Ym-1), ''xn'')
이 성립한다. 여기서 콤마는 원소 ''xn''가 수열에 붙는 부분을 의미한다.
''Xn''과 ''Ym''의 LCS영어를 계산하려면 더 짧은 수열 ''Xn-1 와 ''Ym-1의 LCS영어를 계산해야 한다.
두 수열 X, Y가 같은 기호로 끝나지 않는 경우, X와 Y의 LCS영어는 LCS(Xn, Ym-1)와 LCS(Xn-1, Ym) 중 더 긴 수열이다.
예를 들어, 다음과 같은 두 수열을 보자.
이 두 수열의 LCS영어의 마지막 문자는 수열 X의 마지막 원소인 G로 끝나거나, 그렇지 않을 것이다.
첫 번째 경우: LCS영어가 G로 끝나는 경우이 경우 LCS영어는 K로 끝날 수 없다. 따라서 수열 Y에서 K를 제거해도 된다. LCS(Xn,Ym) = LCS(Xn, Ym-1)이다.
두 번째 경우: LCS영어가 G로 끝나지 않는 경우이 경우 수열 X에서 G를 제거해도 된다. 즉, LCS(Xn,Ym) = LCS(Xn-1, Ym)이다.
어떤 경우든지, 찾는 LCS영어는 LCS(Xn, Ym-1)이거나 LCS(Xn-1, Ym)이다. 이 두 LCS영어는 모두 X와 Y의 공통 부분수열이다. LCS영어(X,Y)는 최장이므로, 그 값은 LCS(Xn, Ym-1)와 LCS(Xn-1, Ym) 중 더 긴 수열이다.
두 수열 ''X'' = (''x''1, ''x''2...''x''m), ''Y'' = (''y''1, ''y''2...''y''n)가 있고, ''X''의 접두사는 ''X''1, 2,...m, ''Y''의 접두사는 ''Y''1, 2,...n라고 하자. ''LCS''(''X''''i'', ''Y''''j'')를 접두사 ''Xi''와 ''Yj''의 최장 공통 부분수열이라고 하면, 이 수열의 집합은 다음과 같다.
:
''Xi'' 와 ''Yj''의 최장 공통 부분 수열을 찾기 위해서, 두 원소 ''xi''와 ''yj''를 비교한다. 만약 같다면 수열 ''LCS''(''X''''i''-1, ''Y''''j''-1)는 ''xi''원소로 확장된다. 만약 같지 않다면, 두 수열 ''LCS''(''X''''i'', ''Y''''j''-1)와 ''LCS''(''X''''i''-1, ''Y''''j'') 중 더 긴 것이 얻어진다. (만약 그 둘이 길이가 같지만 동일하지 않다면 둘 다 얻어진다.) 공식에서 첨자가 1씩 감소했음을 주목하라. 첨자가 0이 되는 상황을 만들 수 있다. 수열의 원소들은 1부터 시작하는 것으로 정의되어 있으므로, 첨자가 0일 때 LCS영어는 비어있다는 조건을 추가한다.
3. 3. 예시
(AGCAT)와 (GAC)의 최장 공통 부분 수열(LCS)을 찾는 과정을 표를 이용하여 단계별로 설명한다.
LCS 계산 과정을 표로 나타내면 다음과 같다.
0 | A | G | C | A | T | |
---|---|---|---|---|---|---|
0 | Ø | Ø | Ø | Ø | Ø | Ø |
G | Ø | Ø | (G) | (G) | (G) | (G) |
A | Ø | (A) | (A), (G) | (A), (G) | (GA) | (GA) |
C | Ø | (A) | (A), (G) | (AC), (GC) | (AC), (GC), (GA) | (AC), (GC), (GA) |
- 초기 설정:
- 빈 수열(Ø)은 비교 대상이 없으므로, 첫 번째 행과 열은 모두 Ø로 채워진다.
- G 비교:
- G는 A와 다르므로, (G, A)의 LCS는 Ø이다.
- G는 G와 같으므로, (G, AG)의 LCS는 (G)가 된다.
- G는 C, A, T와 다르므로, (G, AGC), (G, AGCA), (G, AGCAT)의 LCS는 모두 (G)이다.
- A 비교:
- A는 A와 같으므로, (GA, A)의 LCS는 (A)가 된다.
- A는 G와 다르므로, (GA, AG)의 LCS는 (A) 또는 (G)이다.
- A는 C와 다르므로, (GA, AGC)의 LCS는 (A) 또는 (G)이다.
- A는 A와 같으므로, (GA, AGCA)의 LCS는 (GA)가 된다.
- A는 T와 다르므로, (GA, AGCAT)의 LCS는 (GA)이다.
- C 비교:
- C는 A와 다르므로, (GAC, A)의 LCS는 (A)이다.
- C는 G와 다르므로, (GAC, AG)의 LCS는 (A) 또는 (G)이다.
- C는 C와 같으므로, (GAC, AGC)의 LCS는 (AC) 또는 (GC)이다.
- C는 A와 다르므로, (GAC, AGCA)의 LCS는 (AC), (GC), (GA)이다.
- C는 T와 다르므로, (GAC, AGCAT)의 LCS는 (AC), (GC), (GA)이다.
따라서 (AGCAT)와 (GAC)의 최장 공통 부분 수열은 (AC), (GC), (GA)이다.
3. 4. 역추적 접근
동적 계획법으로 LCS를 계산한 후, 표의 마지막 셀에서 시작하여 화살표를 따라 거슬러 올라가면 실제 LCS를 구할 수 있다.[24] 길이가 감소하는 지점은 두 수열에 공통 원소가 있음을 의미한다. 한 셀에 두 개의 화살표가 있으면 여러 경로가 가능하다.아래는 이러한 역추적 과정을 나타낸 표이다. 굵은 숫자는 (GA) 수열을 찾아내는 경로를 나타낸다.[24]
Ø | A | G | C | A | T | |
---|---|---|---|---|---|---|
Ø | 0 | 0 | 0 | 0 | 0 | 0 |
G | 0 | 0 | 1 | 1 | 1 | 1 |
A | 0 | 1 | 1 | 1 | 2 | 2 |
C | 0 | 1 | 1 | 2 | 2 | 2 |
4. 다른 문제들과의 연관성
두 문자열 \(X_{1 \dots m}\)과 \(Y_{1 \dots n}\)에서, 최단 공통 상위 수열의 길이는 다음 식으로 LCS의 길이와 관련되어 있다.[22]
:\(\left|SCS(X,Y)\right| = n + m - \left|LCS(X,Y)\right|.\)
삽입과 삭제만 가능하고, 치환이 불가능하거나 치환 비용이 삽입이나 삭제 비용의 2배인 경우 편집 거리는 다음과 같다.
:\(d'(X,Y) = n + m - 2 \cdot \left|LCS(X,Y)\right|.\)
5. 동적 계획법을 위한 풀이의 코드
'''함수''' LCSLength(X[1..m], Y[1..n])
C = array(0..m, 0..n)
'''for''' i := 0..m
C[i,0] = 0
'''for''' j := 0..n
C[0,j] = 0
'''for''' i := 1..m
'''for''' j := 1..n
'''if''' X[i] = Y[j]
C[i,j] := C[i-1,j-1] + 1
'''else'''
C[i,j] := max(C[i,j-1], C[i-1,j])
'''return''' C[m,n]
메모이제이션을 사용할 수도 있다.
하나의 LCS를 읽어들이는 함수는 다음과 같다.
'''function''' backtrack(C[0..m,0..n], X[1..m], Y[1..n], i, j)
'''if''' i = 0 '''or''' j = 0
'''return''' ""
'''if ''' X[i] = Y[j]
'''return''' backtrack(C, X, Y, i-1, j-1) + X[i]
'''if''' C[i,j-1] > C[i-1,j]
'''return''' backtrack(C, X, Y, i, j-1)
'''return''' backtrack(C, X, Y, i-1, j)
모든 LCS를 읽어들이는 함수는 다음과 같다.
'''function''' backtrackAll(C[0..m,0..n], X[1..m], Y[1..n], i, j)
'''if''' i = 0 '''or''' j = 0
'''return''' {""}
'''if''' X[i] = Y[j]
'''return''' {Z + X[i] '''for all''' Z '''in''' backtrackAll(C, X, Y, i-1, j-1)}
R := {}
'''if''' C[i,j-1] ≥ C[i-1,j]
R := backtrackAll(C, X, Y, i, j-1)
'''if''' C[i-1,j] ≥ C[i,j-1]
R := R ∪ backtrackAll(C, X, Y, i-1, j)
'''return''' R
두 수열간의 diff를 출력하는 함수는 다음과 같다.
'''함수''' printDiff(C[0..m,0..n], X[1..m], Y[1..n], i, j)
'''만약''' i ≥ 0 '''그리고''' j ≥ 0 '''그리고''' X[i] = Y[j]
printDiff(C, X, Y, i-1, j-1)
print " " + X[i]
'''그렇지 않고 만약''' j > 0 '''그리고''' (i = 0 '''또는''' C[i,j-1] ≥ C[i-1,j])
printDiff(C, X, Y, i, j-1)
print "+ " + Y[j]
'''그렇지 않고 만약''' i > 0 '''그리고''' (j = 0 '''또는''' C[i,j-1] < C[i-1,j])
printDiff(C, X, Y, i-1, j)
print "- " + X[i]
'''그렇지 않으면'''
print ""
`backtrack` 함수는 C 테이블을 계산할 때 이루어진 선택을 백트래킹한다. 접두사의 마지막 문자가 같다면, LCS에 포함되어야 한다. 그렇지 않다면, 와 를 유지하는 것이 어떤 LCS를 가장 크게 만들었는지 확인하고, 동일한 선택을 한다. 길이가 같으면 둘 중 하나를 선택한다. 함수는
i=m
과 j=n
으로 호출한다.`backtrackAll` 함수는 와 를 선택했을 때 결과가 동일하게 길다면, 두 개의 부분 수열을 모두 읽어낸다. 이 함수는 집합 형태로 반환된다. 이 함수는 문자열이 유사할 경우 거의 모든 단계에서 분기될 수 있으므로 다항 시간 내에 실행되지 않는다.
`printDiff` 함수는 C 행렬을 역추적하여 두 시퀀스 간의 차이를 출력한다.
예를 들어, 가 "
XMJYAUZ
"이고 가 "MZJAWXU
"라고 하면, 와 사이의 최장 공통 부분 수열은 "MJAU
"이다. 함수 LCSLength
에 의해 생성된 아래 표 C
는 와 의 접두사 사이의 최장 공통 부분 수열의 길이를 보여준다. 번째 행과 번째 열은 와 사이의 LCS 길이를 보여준다.colspan="2" rowspan="2" | | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
---|---|---|---|---|---|---|---|---|---|
M | Z | J | A | W | X | U | |||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
1 | X | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
2 | M | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
3 | J | 0 | 1 | 1 | 2 | 2 | 2 | 2 | 2 |
4 | Y | 0 | 1 | 1 | 2 | 2 | 2 | 2 | 2 |
5 | A | 0 | 1 | 1 | 2 | 3 | 3 | 3 | 3 |
6 | U | 0 | 1 | 1 | 2 | 3 | 3 | 3 | 4 |
7 | Z | 0 | 1 | 2 | 2 | 3 | 3 | 3 | 4 |
강조 표시된 숫자는 LCS를 읽어낼 때 함수 `backtrack`이 오른쪽 아래에서 왼쪽 위 구석으로 따라갈 경로를 보여준다. 와 의 현재 기호가 같으면 LCS의 일부이며 위와 왼쪽으로 이동한다 ('''굵게''' 표시됨). 그렇지 않으면 숫자가 더 높은 셀에 따라 위 또는 왼쪽으로 이동한다. 이는 와 사이 또는 와 사이의 LCS를 구하는 것에 해당한다.
6. 코드 최적화
실제 상황에 적용하기 위해 알고리즘을 최적화하는 방법은 여러 가지가 있다.
- 원래 알고리즘의 C 행렬 최적화:
원래 알고리즘의 C 행렬은 수열의 길이에 대해 제곱으로 증가한다. 예를 들어, 두 개의 100 길이 수열은 10,000 길이의 행렬과 10,000번의 비교가 필요하다. 하지만 소스 코드 diff나 패치와 같이 실제 상황에서는 파일의 시작과 끝은 거의 변하지 않는다. 따라서 수열의 중간에서 몇 개의 항목만 변했다면 시작과 끝을 제거하여 행렬의 메모리 요구량과 비교 횟수를 줄일 수 있다.
최적화된 코드는 다음과 같다.
```
'''function''' LCS(X[1..m], Y[1..n])
start := 1
m_end := m
n_end := n
''시작 부분에서 일치하는 항목을 제거''
'''while''' start ≤ m_end '''and''' start ≤ n_end '''and''' X[start] = Y[start]
start := start + 1
''끝 부분에서 일치하는 항목을 제거''
'''while''' start ≤ m_end '''and''' start ≤ n_end '''and''' X[m_end] = Y[n_end]
m_end := m_end - 1
n_end := n_end - 1
C = array(start-1..m_end, start-1..n_end)
''변경된 항목만 반복''
'''for''' i := start..m_end
'''for''' j := start..n_end
''알고리즘은 이전과 같이 계속됩니다...''
```
최상의 경우(아무것도 바뀌지 않은 수열)에는 C 행렬이 필요 없어지며, 최악의 경우(맨 앞과 맨 뒤 항목이 바뀐 경우)에는 비교 항목이 2개 추가된다.
- 비교 시간 소모 감소를 위한 최적화:
소스 코드와 같은 문자열에서 각 문자 대신 수열 원소를 라인으로 보면, 각 단계에서 비교적 긴 문자열 간의 비교가 발생할 수 있다. 이를 줄이기 위해 해쉬 함수나 체크섬을 사용하여 수열의 문자열 크기를 줄일 수 있다. 예를 들어, 평균 라인 수가 60자 이상인 소스 코드에서 해쉬나 체크섬은 8~40자 정도이다. 또한, 해쉬와 체크섬의 랜덤화된 특성으로 인해 비교가 더 빠르게 진행될 수 있다.
하지만 이 최적화에는 세 가지 문제점이 있다. 첫째, 해쉬 연산 시간이 소모된다. 둘째, 추가적인 메모리가 필요하다. 셋째, 해쉬 충돌의 가능성이 있다. 소스 코드에서는 드물지만, 다른 두 항목이 같은 해쉬로 축약될 수 있다. 암호학적인 해쉬는 엔트로피가 커서 이러한 문제에 더 적합하지만, 작은 수열에는 적합하지 않을 수 있다.
- 메모리 사용량 최적화:
최장 공통 부분 수열(LCS)의 길이만 필요하다면, 행렬을 또는 로 줄일 수 있다. 동적 계획법은 행렬의 현재와 이전 열만 필요로 하기 때문이다. 허쉬버그 알고리즘은 동일한 이차함수적인 시간과 선형 공간 제한 안에서 최적의 수열을 찾아낼 수 있다.[25]
- 기타 알고리즘
- Chowdhury와 Ramachandran은 최장 공통 부분 수열 길이를 찾기 위한 2차 시간, 선형 공간 알고리즘을 개발했으며[10][9], 실제 실행 시 히르쉬버그 알고리즘보다 캐시 성능이 뛰어나 더 빠르게 실행된다.[10]
- 헌트-시만스키 알고리즘(Hunt–Szymanski algorithm)은 일반적으로 시간 내에 실행된다(일 때). 여기서 은 두 시퀀스 간의 일치하는 횟수이다.[12]
- 제한된 알파벳 크기의 문제의 경우, 네 러시아인 방법(Method of Four Russians)을 사용하여 동적 프로그래밍 알고리즘의 실행 시간을 로그 팩터만큼 줄일 수 있다.[13]
7. 무작위 문자열에서의 동작
Chvátal|츠바탈영어과 Sankoff|산코프영어 (1975)의 연구[14]를 시작으로, 여러 연구자들이 동일한 알파벳에서 무작위로 추출된 두 문자열에서 최장 공통 부분 수열 길이의 동작을 조사했다. 알파벳 크기가 일정할 때 LCS의 예상 길이는 두 문자열 길이에 비례하며, 이 비례 상수(알파벳 크기에 따라 다름)는 Chvátal–Sankoff 상수로 알려져 있다. 정확한 값은 알려져 있지 않지만, 값에 대한 상한과 하한이 증명되었으며,[15] 알파벳 크기의 제곱근에 반비례하여 증가한다는 것이 알려져 있다.[16] 최장 공통 부분 수열 문제의 단순화된 수학적 모델은 Tracy–Widom 분포에 의해 제어되는 것으로 나타났다.[17]
참조
[1]
논문
The Complexity of Some Problems on Subsequences and Supersequences
ACM Press
[2]
논문
The string-to-string correction problem
1974-01
[3]
간행물
A survey of longest common subsequence algorithms
IEEE Computer Society
2000-09-07
[4]
arXiv
Bounds on the Number of Longest Common Subsequences
2003-08-06
[5]
서적
Bioinformatics and the Cell: Modern Computational Approaches in Genomics, Proteomics and Transcriptomics
https://archive.org/[...]
Springer
[6]
서적
Introduction to Algorithms
MIT Press and McGraw-Hill
[7]
문서
Introduction to Algorithms
[8]
논문
A linear space algorithm for computing maximal common subsequences
[9]
논문
Cache-oblivious dynamic programming for bioinformatics
https://ieeexplore.i[...]
2010-07
[10]
서적
Proceedings of the seventeenth annual ACM-SIAM symposium on Discrete algorithm - SODA '06
2006-01
[11]
논문
Cache-oblivious algorithms
https://dl.acm.org/d[...]
2012-01
[12]
웹사이트
Pattern Matching Algorithms
https://books.google[...]
Oxford University Press
1997-05-29
[13]
citation
A faster algorithm computing string edit distances
[14]
citation
Longest common subsequences of two random sequences
[15]
citation
Improved bounds on the average length of longest common subsequences
[16]
citation
Expected length of the longest common subsequence for large alphabets
[17]
citation
Exact asymptotic results for the Bernoulli matching model of sequence alignment
[18]
논문
A Survey of Longest Common Subsequence Algorithms
IEEE Computer Society
[19]
arXiv
Bounds on the Number of Longest Common Subsequences
2003-08-06
[20]
서적
Bioinformatics and the Cell: Modern Computational Approaches in Genomics, Proteomics and Transcriptomics
Springer
[21]
저널
[22]
저널
[23]
서적 인용
Bioinformatics and the Cell: Modern Computational Approaches in Genomics, Proteomics and Transcriptomics
https://archive.org/[...]
Springer
[24]
서적 인용
Introduction to Algorithms
MIT Press and McGraw-Hill
[25]
저널 인용
A linear space algorithm for computing maximal common subsequences
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com