접미사 배열을 사용하여 두 문자열의 가장 긴 공통 부분 문자열 계산


15

복잡성 으로 접미사 배열을 작성하는 방법을 배운 후에는 접미사 배열 의 응용 프로그램을 찾는 데 관심이 있습니다. 이 중 하나는 O ( N ) 시간 에서 두 문자열 사이에서 가장 긴 공통 부분 문자열을 찾는 것 입니다. 인터넷에서 다음 알고리즘을 발견했습니다.영형()영형()

  1. 두 개의 문자열 B 를 하나의 문자열 A B 로 병합
  2. A B 의 접미사 배열을 계산합니다
  3. 컴퓨팅 (긴 공통 프리픽스) 배열
  4. 답은 가장 큰 값입니다 [나는]

나는 그것을 구현하려고 시도했지만 많은 구현 세부 사항이 언급되지 않았기 때문에 (즉, 문자열을 연결할 때 그들 사이에 특수 문자를 넣어야 합니까 ( )?), 많은 테스트 사례에서 코드가 실패했습니다. 누군가이 알고리즘에 대해 더 자세히 설명 할 수 있습니까?

미리 감사드립니다.

참고 : 이 알고리즘의 정확성을 보장하지는 않습니다. 블로그에서 찾았는데 제대로 작동하지 않습니다. 잘못되었다고 생각되면 다른 알고리즘을 제안하십시오.


3
알고리즘을 구현하기 전에 왜 작동하는지 이해하십시오. 두 문자열을 연결하는 방법과 같은 질문에 대답하는 데 도움이 될 수 있습니다.
Yuval Filmus

3
이 알고리즘의 정확성을 의심합니다. 가지고 B C가 거라고 DB의 C의 D를 , 나는 그것을 읽는 방법은 반환됩니다 D 잘못된 것입니다. abcdabcdbcdabc
Khaur

답변:


20

알고리즘이 잘못되었습니다 . 문자열의 접미사 배열과 LCP 배열, 즉 효율적인 구현을 계산하는 방법을 알고 있다고 가정합니다. 주석에서 지적했듯이 각 구성 요소가 무엇이며 왜 작동하는지 이해해야합니다.

우선, 접미사 배열이다 ( 문자열은). 접미사 배열은 기본적으로 오름차순 사전 식 순서로 배열 된 문자열 S 의 모든 접미사입니다 . 구체적으로는, 값 S [ I ]는 의 접미사 것을 나타낸다 S가 위치부터 S [ I ] 올랐 I를 모두 접미어의 사전 식 순서에서 S .S에스S[나는]에스에스[나는]나는에스

다음은 배열입니다. L C P는 [ I ]는 긴 공통의 길이를 나타내는 프리픽스 사이 접미사 부터 S [ I - 1 ]S [ I ]가 . 즉, 사전 순서로 배열 될 때 S의 두 연속 접미사 중에서 가장 긴 공통 접두사 길이를 추적합니다 .[나는]에스[나는1]에스[나는]에스

예로서, 문자열 고려 . 사전 순서의 접미어는 { a , a b b a b c a , a b c a , b a b c a , b b a b c a , b c a , c a } 이므로 S A = [ 7 , 1S=abbabca{a,abbabca,,,,,}1- 인덱스 배열의 경우 , 4 , 3 , 2 , 5 , 6 ] . L C P의 배열 될 L C P = [ - , 1 , 2 , 0 , 1 , 1 , 0 ] .SA=[7,1,4,3,2,5,6]LCPLCP=[,1,2,0,1,1,0]

이제 두 개의 문자열 B가 주어지면 S = A # B 로 연결합니다 . 여기서 #AB 모두에없는 문자 입니다. 이러한 문자 선택을위한 이유는 두 접미사 LCP를 계산할 때, 대답이 너무 B의 #은 거라고 B에서 DB의 d는 , 단지 한번 발생하기 때문에, 비교 결과 (제 문자열의 끝에 끊어 것 두 개의 다른 접미사는 같은 위치에 있지 않습니다 .) 다른 문자열로 "오버플로" 되지 않습니다 .S=A###

이제 배열 에서 연속적인 값만 볼 필요가있는 이유를 알 수 있음을 알 수 있습니다 (인수는 모순과 S A 의 접미어 가 사전 순으로 되어 있다는 사실에 근거합니다 ). 당좌 유지 L C P의 최대 값에 대해 배열 되도록 두 접미사 비교되는 것은 동일한 오리지널 캐릭터에 속하지 않는. 동일한 원래 문자열에 속하지 않는 경우 (하나는 A로 시작 하고 다른 하나는 B에서 ) 가장 큰 공통 부분 문자열의 길이입니다.에스

예를 들어 B = b c를 고려하십시오 . 그런 다음 S = a b c a b c # b c 입니다. 정렬 된 접미어는 { a b c # b c , a b c a b c # b c , b c , b c # b c , b c a==에스=# . S{#,#,,#,#,,#,#}
SA=[4,1,8,5,2,9,6,3,7]LCP=[,3,0,2,2,0,1,1,0]

이제 가장 큰 값은 이지만 S A [ 1 ]S A [ 2 ]대한 것 입니다. 둘 다 문자열 A 에서 시작합니다 . 그래서 우리는 그것을 무시합니다. 한편, L C P [ 4 ] = 2S A [ 3 ] ( B 의 접미사 b c 에 해당 ) 및 S A [ 4 ]에 해당LCP[2]=3SA[1]SA[2]ALCP[4]=2SA[3]bcBSA[4]( A의 접미사 에 해당 ). 따라서 이것은 두 문자열 사이에서 가장 긴 공통 부분 문자열입니다. 실제 문자열 점점 들어 길이를 가지고 2 (최대 값 가능한 L C P 서브 스트링 중 하나에서 시작) S [ 3 ] 또는 S [ 4 ] 이고, (B) (C)를 .bcabc#bcA2 LCPSA[3]SA[4]bc


1
우수한 설명하지만 난 예는 비트 잘못이라고 생각, 정렬 된 접미사는 다음과 같습니다 {#bc,abc#bc,abcabc#bc,bc,bc#bc,bcabc#bc,c,c#bc,cabc#bc}, SA=[7,4,1,8,5,2,9,6,3]그리고LCP=[−,0,3,0,2,2,0,1,1]
사울 마르티네스 Vidals

1

온라인에서 찾은 알고리즘이 완전히 올바르지 않습니다. Paresh가 언급했듯이, 그에게 주어진 예에서는 실패 할 것입니다.

그러나 LCP를 확인하는 동안 다른 문자열의 하위 문자열의 LCP 만 확인합니다. 예를 들어, 문자열 A 및 B의 LCS를 찾는 경우 LCP를 확인하는 동안 접미어 배열의 인접한 항목이 모두 같은 문자열이 아닌지 확인해야합니다.

자세한 내용은 여기를 참조 하십시오 .


1
"이 답변"이라고 말할 때 자신의 답변이나 다른 답변을 의미합니까? 답변 상자 만 사용하여 질문에 대답하고 다른 답변에 대해서는 언급하지 마십시오. 충분한 평판을 얻으면 다른 답변에 의견을 남길 수 있습니다.
David Richerby

0

문자 집합의 일부가 아닌 문자가 구분 기호로 사용되고 접미사 / 접두어 배열이 구분 기호가 포함 된 모든 문자열 을 제외하도록 빌드 된 경우 인용 알고리즘과 실제로 작동해야한다고 생각합니다. 디자이너. 이것은 기본적으로 두 개의 개별 문자열에 대한 접미사 / 접두사 배열을 작성하는 것과 같습니다.

알고리즘에 대한 링크를 게시 한 경우 향후 참조에 도움이됩니다. 참고 위키 피 디아는 의사 및 다른 많은 알고리즘이에 대한 알고리즘을 가지고있다. 온라인에서 사용 가능한 대부분의 표준 언어로 구현되어 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.