빠른 k 불일치 문자열 매칭 알고리즘


10

빠른 k- 미스 매치 문자열 일치 알고리즘을 찾고 있습니다. 길이가 m 인 패턴 문자열 P와 길이가 n 인 텍스트 문자열 T가 주어지면 P가 최대 k 개의 일치하지 않는 T의 하위 문자열과 일치하는 모든 위치를 찾으려면 빠른 (선형 시간) 알고리즘이 필요합니다. 이것은 k- 차이 문제 (편집 거리)와 다릅니다. 불일치는 하위 문자열을 의미하며 패턴은 최대 k 위치에서 다른 문자를 갖습니다. 나는 실제로 k = 1 (최대 1 개의 불일치) 만 필요하므로 k = 1의 특정 경우에 대한 빠른 알고리즘도 충분합니다. 알파벳 크기는 26 (대소 문자를 구분하지 않는 영어 텍스트)이므로 알파벳 크기와 함께 공간 요구 사항이 너무 빨리 커지지 않아야합니다 (예 : FAAST 알고리즘은 알파벳 크기에서 공간 지수를 취합니다. 단백질 및 유전자 서열에만 적합하다).

동적 프로그래밍 기반 접근 방식은 최악의 경우 O (mn) 인 경향이 있으며 너무 느립니다. 이를 위해 Boyer-Moore 알고리즘이 수정되었다고 생각하지만 그러한 논문을 볼 수는 없습니다. 학술지나 출판물에 액세스 할 수있는 구독이 없으므로 모든 참고 문헌은 공개 도메인에 있어야합니다.

자유롭게 사용할 수있는 문서에 대한 포인터 나 참조 또는이 문제에 대한 알고리즘 자체를 대단히 감사하겠습니다.


2
패턴이 고정되어 있지만 (일치하는 텍스트가 다름) 유한 오토 마톤을 작성하고이를 통해 텍스트를 실행할 수 있습니다. 접미사 트리를 사용하는 알고리즘도 있습니다 (일반적으로 텍스트가 일정하고 패턴이 다양하지만 둘 다 다르면 적용 가능). 웹에서 일부 참조를 찾을 수 있습니다. (접미사 트리 기반 알고리즘에 대해 잘 모르기 때문에 아직 답변을 추가하지 마십시오. 아는 사람은이 의견을 무시하십시오.)
Aryabhata

@Aryabhata 감사합니다! 패턴과 텍스트가 모두 변경됩니다. 이러한 맥락에서, 유한 오토 마톤을 구축하는 것은 특히 1 개의 불일치에 대한 범위를 포함 할 때 너무 비쌀 것입니다. 접미사 트리 / 접미사 배열에 관해서는, 나는 그것들을 사용한 적이 없으며 그것에 대해 거의 알지 못했지만, 정확하게 일치하기 위해 구축이 느리고 효율적이라는 인상을 받았습니다. 그러나 나는이 옵션을 더 탐구 할 것이다. 이 방향 또는 다른 방향의 포인터가 가장 유용합니다!
Paresh

1
아니요, 접미사 트리는 대략적인 일치에도 사용할 수 있습니다. 위키 주장에 대해 Atleast : en.wikipedia.org/wiki/Suffix_tree
Aryabhata

답변:


5

이 문제에 접미사 배열을 사용할 수 있습니다. 여기에는 사전 순으로 정렬 된 문자열의 각 접미사의 시작 위치가 포함됩니다. 그것들은 복잡성으로 순진하게 구성 될 수 있지만 , 복잡성 으로 구성하는 방법이 있습니다. 예를 들어 thisthis를 참조하십시오 . 이 접미사 배열 SA를 호출하겠습니다.Θ ( N )O(nlogn)Θ(n)

접미사 배열을 구성한 후에는 접미사 배열에 대한 LCP (Longest Common Prefix) 배열을 구성해야합니다. LCP 배열은 접미사 배열에있는 두 개의 연속 접두사 사이의 가장 긴 공통 접두사 길이 (사전 연속 접미사)를 저장합니다. 따라서, LCP [i]는 SA [i]와 SA [i + 1] 사이에서 가장 긴 공통 접두사 길이를 포함합니다. 이 배열은 선형 시간으로 구성 할 수도 있습니다 . 좋은 참조는 here , herehere 을 참조하십시오.

이제, 가장 긴 접두사 공통의 길이를 계산하기 위해 어떤 접미사 트리에서 두 접미사 (대신 연속 접미사), 우리는 몇 가지 사용할 필요가 RMQ의 데이터 구조를. 접미사 배열에서 위치 와 ( )를 갖는 두 접미사 사이의 가장 긴 공통 접두사 길이는 위의 참조에 나와 있으며 (배열이 접미사 트리로 시각화 된 경우 쉽게 볼 수 있음) , 로 얻을 수 있습니다 . 좋은 RMQ는 또는 시간으로 배열을 사전 처리하고 에서 형식의 쿼리에 응답 할 수 있습니다.v u < v m i n u < = k < = v 1 L C P [ k ] L C P O ( n ) O ( n log n ) L C P [ u , v ] O ( 1 )uvu<vminu<=k<=v1LCP[k]LCPO(n)O(nlogn)LCP[u,v]O(1)시각. 참조 여기 간결 RMQ 알고리즘에 대한, 그리고 여기 RMQ의에 좋은 튜토리얼 및 LCA와 RMQs 사이의 관계 (및 감소)에 대한. 이것은 또 다른 좋은 대안 접근법이 있습니다.

이 정보를 사용하여 두 문자열 사이에 구분 기호를 사용하여 두 문자열을 연결하기 위해 접미어 배열 및 관련 배열 (위에 설명 된대로)을 구성합니다 (예 : T # P, 여기서 '#'은 두 문자열에서 발생하지 않음). 그런 다음 "kangaroo"방법을 사용하여 k 불일치 문자열 일치를 수행 할 수 있습니다. 이것이것은 접미사 트리의 맥락에서 캥거루 방법을 설명하지만 접미사 배열에도 직접 적용될 수 있습니다. 인덱스마다 텍스트 , 찾기 의 접미사 시작 그리고 접미사 0이 시작은 제 불일치 할 때 매칭 발생 후 위치 부여T L C P T i P P T [ i ] l 0 T P L C P T [ i + l 0 + 1 ] P [ l 0 + 1 ]iTLCPTiPP와 . 이 길이를 . 와 에서 일치하지 않는 문자를 건너 뛰고 나머지 문자열과 일치 시키십시오. 즉, 및 의 를 다시 찾으십시오 . 불일치 또는 문자열 마감 이 나올 때까지이 과정을 반복하십시오 . 각 는 입니다. 각 인덱스 에 대해 가 있으며 , 이는 의 총 복잡성을 제공합니다 .T[i]l0TPLCPT[i+l0+1]P[l0+1]L C P O ( 1 ) O ( k ) L C P i T O ( n k )kLCPO(1)O(k) LCPiTO(nk)

또는 인 경우 의 총 복잡성을 제공하는 RMQ 구현을 더 쉽게 사용 했지만 위에서 설명한 것처럼 수행 할 수 있습니다 . 이 문제에 대한 다른 직접적인 방법이있을 수 있지만 이것은 많은 유사한 문제에 적용될 수있는 강력하고 일반적인 접근법입니다.O ( N K + N 로그 N ) m = O ( 없음 ) O ( N K )O(nk+(n+m)log(n+m))O(nk+nlogn)m=O(n)O(nk)


큰! 나는 지금 나의 TODO리스트에 대한 몇 가지 독서를 :-)
아리 아바타

두 번째 단락의 siam.org 링크는 깨졌지만 링크 된 논문은 epubs.siam.org/doi/pdf/10.1137/1.9781611972917.3
leecbaker

4

아래 예상 알고리즘 (다른 확장 될 수 만드는 것이 ). (그렇지만 입증하기 위해 계산을 수행하지는 않았습니다).K O ( N k는 + m )O(n+m)kO(nk+m)

이 아이디어는 정확한 하위 문자열 일치를위한 Rabin-Karp 롤링 해시 알고리즘 과 유사합니다 .

아이디어는 길이 의 각 문자열을 각각 크기 의 블록 으로 분리하고 각 블록에 대한 롤링 해시 ( 해시 값 제공)를 계산하고 해당 해시 값을 패턴의 것과 비교 합니다.2 k m / 2 k 2 k 2 km2km/2k2k2k

해당 값 에서 최대 불일치를 허용 합니다.k

개 이상의 불일치가 발생하면 거부하고 계속 진행합니다. 그렇지 않으면 우리는 대략적인 일치를 시도하고 확인합니다.k

나는 접미사 트리 기반 접근법을 사용하는 것보다 실제로 더 빠르며 코딩 / 유지 보수가 더 쉬울 것으로 예상합니다 (캐비티 : 직접 시도하지 않았습니다).


설명이 필요합니다. ".. 길이 m의 각 문자열을 각각 m / 2k 크기의 2k 블록으로 분리합니다."는 길이 m의 길이 (m)를 2k 블록으로 분리한다는 것을 의미합니다. 그리고이 해시는 롤링 해시 방법으로 O (n)으로 계산할 수 있습니다. 그런 다음 패턴 문자열도 2k 블록으로 분할되고 해당 해시가 비교되어 최대 k 개의 블록이 불일치하도록 허용합니다. 그렇다면 불일치 횟수가 k를 초과하는 모든 경우를 잠재적으로 버릴 수 있습니다. 내가 제대로 이해 했습니까?
Paresh

@Paresh : 그렇습니다. 해시 가 있기 때문에 대신 입니다. Ω ( n k ) O ( n )kΩ(nk)O(n)
Aryabhata

나는이 접근법을 좋아한다! 그러나이 방법은 일반적으로 빠르지 만 일치 횟수가 많으면 (O (n) 일치) O (mnk)로 저하됩니다. 이것을 염두에두고, 두 입력이 동일한 입력에 대해 충돌을 일으킬 수 없다는 가정하에 두 개의 롤링 해시를 유지했습니다 (속도를보고 싶기 때문에 수학적으로하지 않았습니다). 이런 식으로, 우리는 두 해시가 동의한다면 문자별로 일치하는지 확인할 필요가 없습니다. 이것은 일반적으로 매우 빠르지 만 일치하는 수가 많으면 느립니다. 이것과 당신이 제안한 방식으로, 큰 경기에서는 느 렸습니다.
Paresh

텍스트를 블록 대신 크기의 블록 으로 나누면 최악의 경우 더 빨라질 수 있습니다 . 패턴은 (완전한 사각형이 아닌 경우 +1) 블록 으로 나뉘어 각 블록을 비교합니다. 불일치 수가 적은 경우에는 접근 방식보다 느리지 만 최악의 경우에는 여야한다고 생각합니다 (이를 제대로 확인하지는 않았습니다). 나는 이것을 시도하지 않았지만 제안한대로 먼저 접미사 트리 / 배열을 탐색 할 것입니다. 그들은 좋은 경계를 제공하는 것 같습니다. 감사! m/2kmm/2k O(nkmO(nkm)
Paresh

@Paresh : 개정 내역에서 볼 수는 없지만 처음에는 방식을 사용했지만 현재 방식으로 변경했습니다. 내가 사용하는 생각 더 좋다. 불필요하게 너무 많은 해시 값을 계산하고 있습니다. 물론, 더 나은 것은 데이터에 달려 있습니다. 물론, 대신 또는 등을 시도 할 수도 있습니다 . btw, 최악의 경우 및 접근법 모두에 대해 입니다 . m/2k2kk+1k+cΩ(nm)mm/2k2kk+1k+cΩ(nm) m/2kmm/2k
Aryabhata
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.