Hızlı k uyuşmazlığı dize eşleme algoritması


10

Hızlı k-mismatch dize eşleme algoritması arıyorum. M uzunluğunda bir desen dizesi P ve n uzunluğunda bir metin dizisi T verildiğinde, P'nin T'nin bir alt dizesini en fazla k uyuşmazlığıyla eşleştirdiği tüm konumları bulmak için hızlı (doğrusal zaman) algoritmasına ihtiyacım var. Bu, k farklılıkları sorunundan farklıdır (düzenleme mesafesi). Uyumsuzluk alt dizeyi ifade eder ve desenin en fazla k konumunda farklı bir harfi vardır. Gerçekten sadece k = 1 (en fazla 1 uyumsuzluk) gerektirir, bu nedenle k = 1 özel durumu için hızlı bir algoritma da yeterli olacaktır. Alfabe boyutu 26'dır (büyük / küçük harf duyarsız ingilizce metin), bu nedenle boşluk gereksinimi alfabenin boyutuyla çok hızlı büyümemelidir (örneğin, FAAST algoritması, sanırım, alfabenin boyutunda üstel alan alır ve bu yüzden sadece protein ve gen dizileri için uygundur).

Dinamik programlama tabanlı bir yaklaşım en kötü durumda O (mn) olma eğilimindedir ve bu çok yavaş olacaktır. Bunun için Boyer-Moore algoritmasında değişiklikler olduğuna inanıyorum, ancak bu tür kağıtlara ellerimi alamıyorum. Akademik dergilere veya yayınlara erişmek için aboneliğim yok, bu nedenle referansların kamuya açık olması gerekir.

Bu sorun için herhangi bir işaretçi veya serbestçe kullanılabilir belgelere veya algoritmanın kendisine yapılan referansları takdir ediyorum.


2
Desen sabitse (ancak eşleşecek metin değişiklik gösteriyorsa), potansiyel olarak sonlu bir otomasyon oluşturabilir ve metni bu yolla çalıştırabilirsiniz. Ek ağaçları kullanan algoritmalar da vardır (genellikle metin sabitse ve desen değişirse iyidir, ancak her ikisi de değişirse uygulanabilir), web üzerinde bazı referanslar bulabilirsiniz. (Henüz bir cevap eklememek değil gibi ben sonek ağacı tabanlı algoritmalar çok emin değilim, eğer biri biliyorsa bu yorumu görmezden çekinmeyin lütfen).
Aryabhata

@Aryabhata Teşekkürler! Hem desen hem de metin değişir. Bu bağlamda, özellikle 1 uyumsuzluk kapsamı dahil edildiğinde, sınırlı bir otomasyon oluşturmak çok pahalı olacaktır. Son ek ağaçlar / sonek dizilerine gelince, onları hiç kullanmadım ve onlar hakkında çok az şey bilmiyorum, ancak temel olarak tam eşleme için yavaş inşa edildikleri ve verimli oldukları izlenimi altındaydım. Ancak bu seçeneği daha ayrıntılı bir şekilde araştıracağım. Bu yönde veya başka herhangi bir yönde işaretçiler en yararlı olacaktır!
Paresh

1
Hayır, son ek ağaçlar yaklaşık eşleşmeler için de kullanılabilir. En az wiki iddia ediyor: en.wikipedia.org/wiki/Suffix_tree
Aryabhata

Yanıtlar:


5

Sonek dizileri bu sorun için kullanılabilir. Sözcükbilimsel sıralamaya göre dizenin her sonekinin başlangıç ​​konumlarını içerirler. Her ne kadar karmaşıklığında saf olarak inşa edilebilirlerse de , bunları Θ ( n ) karmaşıklığında inşa etmek için yöntemler vardır . Örneğin bu ve buna bakın . Bu sonek dizisi SA diyelim.O(nlogn)Θ(n)

Sonek dizisi oluşturulduktan sonra, sonek dizisi için bir En Uzun Ortak Önek (LCP) dizisi oluşturmamız gerekir. LCP dizisi, sonek dizisindeki iki ardışık önek (sözlükçik ardışık sonekler) arasındaki en uzun ortak önek uzunluğunu saklar. Bu nedenle, LCP [i], SA [i] ve SA [i + 1] arasındaki en uzun ortak önek uzunluğunu içerir. Bu dizi doğrusal zamanda da oluşturulabilir: bazı iyi referanslar için buraya , buraya ve buraya bakın.

Şimdi, sonek ağacındaki herhangi bir iki sonek için ortak olan en uzun ön ekin uzunluğunu hesaplamak için (ardışık sonekler yerine), bazı RMQ veri yapısını kullanmamız gerekiyor . Yukarıdaki referanslarda gösterilmiştir (ve dizi bir sonek ağacı olarak görselleştiriliyorsa kolayca görülebilir), sonek dizisinde ve v ( u < v ) konumlarına sahip iki sonek arasındaki en uzun ortak önek uzunluğunun , m i n u < = k < = v - 1 L C P [ k ] olarak elde edilebiliruvu<vminu<=k<=v1LCP[k]. İyi bir RMQ işlem öncesi olabilir Dizi O ( n ) ya da O ( n, log n ) formunun sorguları için zaman ve cevap L Cı- P [ u , v ] içinde , O ( 1 ) zaman. Bkz burada bir succint RMQ algoritması için, ve burada RMQ en iyi bir öğretici ve LCA ve RMQs arasındaki ilişki (ve indirimleri) için. Bunun güzel bir alternatif yaklaşımı var.LCPO(n)O(nlogn)LCP[u,v]O(1)

Bu bilgilerle, iki dizenin aradaki bir sınırlayıcı ile birleştirilmesi için (yukarıda açıklandığı gibi) sonek dizisini ve ilişkili dizileri oluştururuz (örneğin T # P, her iki dizede '#' oluşmaz). Ardından, "kanguru" yöntemini kullanarak k uyuşmazlığı dizesi eşleştirmesi yapabiliriz. Bu ve bu , kanguru yöntemini sonek ağaçları bağlamında açıklar, ancak sonek dizilerine de doğrudan uygulanabilir. Her dizin için metni T bulmak L Cı- P ve ekinin T başlayan i ve son ek PiTLCPTiPBu, T [ i ] ile eşleştirirken ilk uyumsuzluğun meydana geleceği konumu verir . Bu uzunluk l 0 olsun . Hem uyuşmayan karakteri atla T ve P ve kalan dizeleri eşleştirmeye çalışın. Kendisine, yeniden bulmak L Cı- P ve T [ i + l 0 + 1 ] ve p [ l 0 + 1 ] . K uyuşmazlıkları elde edene veya dize bitene kadar bu işlemi tekrarlayın . Her biriPT[i]l0TPLCPT[i+l0+1]P[l0+1]k olan O ( 1 ) . Var O ( k ) L Cı- P ', bulunduğu her bir dizin için s ı arasında T , bu toplam karmaşıklığını veren O ( n, k ) .LCPO(1)O(k) LCPiTO(nk)

O(nk+(n+m)log(n+m))O(nk+nlogn)m=O(n)O(nk)


Harika! TODO listemde şimdi biraz okuma var :-)
Aryabhata

İkinci paragraftaki siam.org bağlantısı koptu, ancak bağlantılı makale burada bulunabilir epubs.siam.org/doi/pdf/10.1137/1.9781611972917.3
leecbaker

4

O(n+m)kO(nk+m)

Fikir, kesin alt dize maçları için Rabin-Karp haddeleme karma algoritmasına benzer .

m2km/2k2k2k

k

k

Ben beklemek (uyarı: kendim denemedim) bu muhtemelen pratikte daha hızlı olacak ve belki de kod / bakım, bir ek ağacı tabanlı yaklaşım kullanmak daha kolay olacaktır.


Sadece bir açıklamaya ihtiyacım var. ".. m uzunluğundaki her dizeyi her biri m / 2k büyüklüğünde 2k bloklara ayırın ..." ile, T (n uzunluğunda) m uzunluğundaki her alt dizeyi 2k bloklara ayırmak anlamına gelir. Ve bu karma haddeleme karma yöntemi ile O (n) cinsinden hesaplanabilir. Daha sonra, desen dizisi de 2k bloğa bölünecek ve karşılık gelen karmalar karşılaştırılacak ve en az k bloğunun uyumsuzluğuna izin verecek. Eğer öyleyse, yanlış eşleşme sayısının k'dan fazla olduğu tüm durumları potansiyel olarak atabiliriz. Doğru mu anladım?
Paresh

kΩ(nk)O(n)

Bu yaklaşımı seviyorum! Ancak, bu yaklaşım genel olarak hızlıdır, ancak eşleşme sayısı yüksekse (O (n) eşleşmeler) O (mnk) değerine düşer. Bunu akılda tutarak, her ikisi de aynı girdi için bir çarpışmaya sahip olamayacağı varsayımı altında iki haddeleme karma değerini korudum (hızı görmek istediğim için bunu matematiksel olarak yapmadım). Bu şekilde, iki karma kabul ederse bir char-by-char doğrulaması gerekmiyor. Bu genel olarak oldukça hızlıdır, ancak maç sayısı fazla ise bu da yavaştır. Bununla ve önerdiğiniz şekilde, büyük maçlar için yavaştı.
Paresh

Metni bölersek, en kötü durumda bu daha hızlı yapılabilir.mm/2kmO(nkm)

mm/2k2kk+1k+cΩ(nm)mm/2k
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.