주어진 n 개의 문자열 중 하나가 다른 문자열입니까?


9

문자열 가정 합니다. 해당 문자열 중 하나가 컬렉션에있는 다른 문자열의 하위 문자열인지 알고 싶습니다. 즉, 다음 작업에 대한 알고리즘을 원합니다.nS1,,Sn

입력 :S1,,Sn

출력 : 예 : 는 및 의 하위 문자열 임 ) 또는 그러한 가 없는 경우 Nonei,jS나는S제이i제이i,제이

이를위한 효율적인 알고리즘이 있습니까?

"substring"을 "prefix"로 바꾸면 효율적인 알고리즘이 있습니다 (문자열을 정렬 한 다음 선형 스캔을 수행하여 인접한 문자열을 비교합니다. 정렬하면 하위 문자열이 인접 해 있음). 그러나 문자열이 다른 문자열의 하위 문자열인지 테스트하는 것이 더 어려워 보입니다. 순진한 알고리즘은 모든 쌍 를 반복하는 것이지만 하위 문자열 테스트가 필요합니다. 더 효율적인 알고리즘이 있습니까?나는,제이Θ(2)

이것을 "모든 쌍 하위 문자열 테스트"또는 이와 유사한 것으로 부를 수있을 것 같습니다.

내 궁극적 인 목표는 컬렉션에서 다른 문자열을 제거하여 문자열을 다른 문자열로 만들지 않도록 컬렉션을 정리하는 것입니다.


힌트 : 접미사 배열.
가명

부수적으로, 는 부분 문자열을 찾을 때 제거하면 올바르지 않습니다. 더 적을 것입니다. 또한 더 긴 문자열은 더 짧은 문자열에 나타날 수 없으므로 길이별로 정렬해야합니다. 여기서 다시 가 잘못되었습니다. Θ(2)Θ(2)
Alexis Wilke

@AlexisWilke, 는 정확합니다. 최악의 경우 하위 문자열 테스트 횟수입니다 (최악의 경우 문자열이 다른 문자열이 아닌 경우). 길이를 기준으로 정렬하면 2 배만 발생하므로 무증상에는 영향을 미치지 않습니다. Θ(2)
DW

답변:


6

선형 시간에 접미사 트리를 작성하고 전체 문자열 (노드 당 일정한 시간)에 해당하는 내부 노드가 있는지 확인할 수 있습니다.

더 자세하게, 우리는 문자열이 있다고 가정 에스1,,에스Σ.

  1. A (일반화) 구축 접미사 트리 의를에스1$1,에스2$2,,에스$ 쌍별 구별 터미널 마커 $1,,$Σ.

    Ukkonen의 알고리즘을 사용하면 선형 시간으로 수행 할 수 있습니다. 모든 문자열 길이의 합계에서 선형입니다.

  2. 당신이 레이블을 잎으로 가정 (나는,제이) 이들이 접미사를 나타내는 경우 에스나는[제이..|에스나는|]에스나는나무를 가로 질러서 라벨이 붙은 잎 (나는,0)즉, 전체 문자열에 해당하는 잎입니다.

    이것은 트리 크기에서 선형으로 시간이 걸리며 입력 크기에서 선형으로 나타납니다.

  3. 부모의 후손 (나는,0) (이것은 가장자리에 라벨이 붙어 있습니다. $나는) 세트에서 모든 일치를 나타냅니다. 이것은 접미사 트리의 기본 불변 값에서 비롯됩니다. 어떤 잎으로도 내려 가서 하나의 성냥을 찾으십시오.(나는,0)).

    다시 선형 시간이 걸립니다.

별개의 터미널 마커는 실제로 필요하지 않습니다. 리프마다 여러 레이블을 허용하는 한 모든 문자열을 종료하는 데 사용되는 단일 문자열이면 충분합니다.

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