2 개의 문자열 중에서 가장 긴 공통 서브 시퀀스를 찾기 위해 동적 프로그래밍 솔루션을 구현했습니다. 이 알고리즘을 일반화하여 3 개의 문자열 중에서 LCS를 찾는 방법이 있지만 내 연구에서는이 방법에 대한 정보를 찾지 못했습니다. 어떤 도움을 주시면 감사하겠습니다.3 개의 문자열 중에서 가장 긴 공통 서브 시퀀스
답변
반복 관계를 일반화합니다.
세를 들어 문자열 :
dp[i, j, k] = 1 + dp[i - 1, j - 1, k - 1] if A[i] = B[j] = C[k]
max(dp[i - 1, j, k], dp[i, j - 1, k], dp[i, j, k - 1]) otherwise
대답은 비슷한 질문 here에서 가져온 것입니다.
복사하여 붙여 넣기 [답변] (http://stackoverflow.com/a/5057362/3375713). 적어도 답안에는 원저자의 이름을 언급해야합니다. –
2 개의 문자열 A와 B의 LCS (Longest Common Subsequence)를 찾으려면 게시 한 링크와 같이 대각선으로 2 차원 배열을 탐색 할 수 있습니다. 배열의 모든 요소는 하위 문자열 A '및 B'의 LCS를 찾는 문제에 해당합니다 (A는 행 번호로 자르고 B는 열 번호로 자름). 이 문제는 배열의 모든 요소 값을 계산하여 해결할 수 있습니다. 배열 요소의 값을 계산할 때 주어진 값을 계산하는 데 필요한 모든 하위 문제가 이미 해결되었음을 확신해야합니다. 그래서 2 차원 배열을 대각선으로 가로 지르는 것입니다.
이 해결 방법은 N 개의 문자열 사이에서 가장 긴 공통 하위 시퀀스를 찾을 수 있도록 확장 할 수 있지만 N 개의 차원 배열을 반복하는 일반적인 방법이 필요합니다. 모든 하위 문제에 대한 해결책이 필요한 경우에만 요소에 도달합니다. 해결되었습니다.
N 차원 배열을 특별한 순서로 반복하는 대신 재귀 적으로 문제를 해결할 수도 있습니다. 재귀를 사용하면 중간 지점 솔루션을 저장하는 것이 중요합니다. 많은 지점에서 동일한 중간 솔루션이 필요하기 때문입니다. 나는 이것을 수행하는 C#의 작은 예제를 작성했다 :
string lcs(string[] strings)
{
if (strings.Length == 0)
return "";
if (strings.Length == 1)
return strings[0];
int max = -1;
int cacheSize = 1;
for (int i = 0; i < strings.Length; i++)
{
cacheSize *= strings[i].Length;
if (strings[i].Length > max)
max = strings[i].Length;
}
string[] cache = new string[cacheSize];
int[] indexes = new int[strings.Length];
for (int i = 0; i < indexes.Length; i++)
indexes[i] = strings[i].Length - 1;
return lcsBack(strings, indexes, cache);
}
string lcsBack(string[] strings, int[] indexes, string[] cache)
{
for (int i = 0; i < indexes.Length; i++)
if (indexes[i] == -1)
return "";
bool match = true;
for (int i = 1; i < indexes.Length; i++)
{
if (strings[0][indexes[0]] != strings[i][indexes[i]])
{
match = false;
break;
}
}
if (match)
{
int[] newIndexes = new int[indexes.Length];
for (int i = 0; i < indexes.Length; i++)
newIndexes[i] = indexes[i] - 1;
string result = lcsBack(strings, newIndexes, cache) + strings[0][indexes[0]];
cache[calcCachePos(indexes, strings)] = result;
return result;
}
else
{
string[] subStrings = new string[strings.Length];
for (int i = 0; i < strings.Length; i++)
{
if (indexes[i] <= 0)
subStrings[i] = "";
else
{
int[] newIndexes = new int[indexes.Length];
for (int j = 0; j < indexes.Length; j++)
newIndexes[j] = indexes[j];
newIndexes[i]--;
int cachePos = calcCachePos(newIndexes, strings);
if (cache[cachePos] == null)
subStrings[i] = lcsBack(strings, newIndexes, cache);
else
subStrings[i] = cache[cachePos];
}
}
string longestString = "";
int longestLength = 0;
for (int i = 0; i < subStrings.Length; i++)
{
if (subStrings[i].Length > longestLength)
{
longestString = subStrings[i];
longestLength = longestString.Length;
}
}
cache[calcCachePos(indexes, strings)] = longestString;
return longestString;
}
}
int calcCachePos(int[] indexes, string[] strings)
{
int factor = 1;
int pos = 0;
for (int i = 0; i < indexes.Length; i++)
{
pos += indexes[i] * factor;
factor *= strings[i].Length;
}
return pos;
}
내 코드 예제는 더 이상 최적화 될 수있다. 캐시되는 문자열의 대부분은 중복이며 일부는 추가 된 하나의 문자 만 추가하여 중복됩니다. 이렇게하면 입력 문자열이 커질 때 필요한 것보다 많은 공간이 사용됩니다. 입력에
"666222054263314443712", "5432127413542377777"는 LCS 반환 "6664664565464057425"
정말 대신 2의 3 문자열 일 변경 "54442"
- 1. Ocaml에서 가장 긴 공통 서브 시퀀스
- 2. 가장 긴 공통 서브 시퀀스 알고리즘
- 3. 세 문자열의 가장 긴 공통 하위 시퀀스
- 4. 여러 시퀀스에 대해 가장 긴 공통 서브 시퀀스
- 5. 가장 긴 공통 부분 시퀀스 번호
- 6. O (n)에서 가장 긴 공통 서브 시퀀스
- 7. 가장 긴 공통 부분 시퀀스 Postgresql
- 8. 가장 긴 연속 서브 시퀀스 알고리즘
- 9. LRS 배열로 향상된 factor oracle을 사용하여 여러 문자열 중에서 가장 긴 공통 부분 문자열 찾기
- 10. 가장 긴 공통 부분 문자열 문제
- 11. 가장 긴 공통 서브 시퀀스 문제에 대한 입력 크기에 대한 플롯팅 시간
- 12. 역순으로 서브 시퀀스가있는 가장 긴 연속 서브 시퀀스를 찾는 방법
- 13. 가장 긴 회문의 서브
- 14. 가장 긴 공통 서브 시퀀스 길이 함수가 올바른 길이를 반환하지 않습니까?
- 15. 지수 시간에서 가장 긴 공통 서브 시퀀스를 찾는 방법은 무엇입니까?
- 16. 가장 긴 공통 부분 시퀀스의 수를 계산하는 방법
- 17. Trie를 사용하여 가장 긴 공통 부분 문자열 찾기
- 18. 고유 한 가장 긴 공통 서브 시퀀스의 수 찾기
- 19. 두 개의 정수 배열 중에서 가장 긴 교차점을 찾습니다.
- 20. 각 요소에서 가장 길게 증가하는 서브 시퀀스
- 21. 문자열에서 가장 긴 반복 시퀀스 찾기
- 22. 가장 긴 공통 시퀀스에 대한 코드 최적화
- 23. 가장 긴 공통 접두어를 찾으십니까? 두 개의 문자열에서
- 24. 상수 메모리가있는 가장 긴 공통 부분 문자열입니까?
- 25. 테이블을 업데이트하여 3 개의 임의의 문자열 중에서 선택하십시오.
- 26. 문자열에서 가장 긴 유사한 서브 시퀀스를 찾으십시오.
- 27. SQL : 3 개의 테이블 중에서 선택
- 28. 3 중에서 가장 가까운 두 숫자 검색
- 29. SQL 가장 긴 접두사 문자열
- 30. 가장 긴 반복되는 부분 문자열
됩니다 아니다 "일반화". 일반화하는 경우 문자열의 수에 관계없이 작동해야합니다. –
Ah. 이 경우에는 3 개의 문자열에 대해 작업 할 필요가 있으며 꼭 필요한 것은 아닙니다. –