Algoritmo di corrispondenza stringhe k non corrispondente


10

Sto cercando un algoritmo di corrispondenza delle stringhe k-mismatch veloce. Data una stringa di modello P di lunghezza m e una stringa di testo T di lunghezza n, ho bisogno di un algoritmo veloce (tempo lineare) per trovare tutte le posizioni in cui P corrisponde a una sottostringa di T con al massimo k non corrispondenti. Questo è diverso dal problema delle differenze k (modifica distanza). Una mancata corrispondenza implica la sottostringa e il modello ha una lettera diversa nella maggior parte delle posizioni k. Ho davvero bisogno solo di k = 1 (al massimo 1 discrepanza), quindi basterà anche un algoritmo veloce per il caso specifico di k = 1. La dimensione dell'alfabeto è 26 (testo in inglese senza distinzione tra maiuscole e minuscole), quindi il requisito di spazio non dovrebbe crescere troppo velocemente con la dimensione dell'alfabeto (ad esempio, l'algoritmo FAAST, credo, occupa spazio esponenziale nella dimensione dell'alfabeto, e così è adatto solo per sequenze di proteine ​​e geni).

Un approccio basato sulla programmazione dinamica tenderà ad essere O (mn) nel peggiore dei casi, che sarà troppo lento. Credo che ci siano modifiche all'algoritmo di Boyer-Moore per questo, ma non sono in grado di mettere le mani su tali documenti. Non ho un abbonamento per accedere a riviste o pubblicazioni accademiche, quindi eventuali riferimenti dovranno essere di dominio pubblico.

Gradirei molto qualsiasi suggerimento o riferimento a documenti liberamente disponibili o l'algoritmo stesso per questo problema.


2
Se il modello è fisso (ma il testo da abbinare varia), potresti potenzialmente creare un automa finito ed eseguire il testo attraverso quello. Esistono anche algoritmi che utilizzano gli alberi dei suffissi (di solito buoni se il testo è costante e il modello varia, ma applicabile anche se entrambi variano), potresti essere in grado di trovare alcuni riferimenti sul web. (Non aggiungo ancora una risposta poiché non sono molto sicuro degli algoritmi basati sull'albero dei suffissi, se qualcuno lo sa, non esitate a ignorare questo commento).
Aryabhata,

@Aryabhata Grazie! Sia il modello che il testo cambiano. In tale contesto, la costruzione di un automa finito sarebbe troppo costosa, soprattutto se si include l'ambito per 1 discrepanza. Per quanto riguarda gli alberi di suffisso / array di suffissi, non li ho mai usati e ne so poco, ma ho avuto l'impressione che siano lenti da costruire ed efficienti principalmente per la corrispondenza esatta. Ma esplorerò ulteriormente questa opzione. Qualsiasi puntatore in questa direzione, o in qualsiasi altra direzione, sarebbe molto utile!
Paresh,

1
No, gli alberi di suffisso possono essere utilizzati anche per corrispondenze approssimative. Almeno il wiki afferma così: en.wikipedia.org/wiki/Suffix_tree
Aryabhata

Risposte:


5

Le matrici di suffissi possono essere utilizzate per questo problema. Contengono le posizioni iniziali di ciascun suffisso della stringa ordinate in ordine lessicografico. Anche se possono essere costruiti ingenuamente nella complessità , ci sono metodi per costruirli nella complessità Θ ( n ) . Vedi per esempio questo e questo . Chiamiamo questo suffisso array SA.O(nlogn)Θ(n)

Una volta che la matrice di suffissi è stata costruita, dobbiamo costruire una matrice di prefisso comune più lungo (LCP) per la matrice di suffissi. L'array LCP memorizza la lunghezza del prefisso comune più lungo tra due prefissi consecutivi nell'array di suffissi (suffissi lessicografici consecutivi). Pertanto, LCP [i] contiene la lunghezza del prefisso comune più lungo tra SA [i] e SA [i + 1]. Questo array può anche essere costruito in tempo lineare: vedi qui , qui e qui per alcuni buoni riferimenti.

uvu<vminu<=k<=v1LCP[k]LCPO(n)O(nlogn)LCP[u,v]O(1)

iTLCPTiPPT[i]l0TPLCPT[i+l0+1]P[l0+1]kLCPO(1)O(k) LCPiTO(nk)

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


Grande! Ho qualche lettura sul mio elenco TODO ora :-)
Aryabhata,

Il link siam.org nel secondo paragrafo è interrotto, ma il documento collegato può essere trovato qui epubs.siam.org/doi/pdf/10.1137/1.9781611972917.3
leecbaker

4

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

L'idea è simile all'algoritmo di hash rolling Rabin-Karp per esatte corrispondenze di sottostringa.

m2km/2k2k2k

k

k

Mi aspetto (avvertimento: non l'ho provato da solo) questo sarà probabilmente più veloce in pratica, e forse più facile da programmare / mantenere, rispetto all'uso di un approccio basato sull'albero dei suffissi.


Ho solo bisogno di un chiarimento. Per "... separare ogni stringa di lunghezza m in 2k blocchi di m / 2k dimensioni ciascuno ...", si intende che separare ogni sottostringa di lunghezza m in T (di lunghezza n) in blocchi 2k. E questo hash può essere calcolato in O (n) con il metodo rolling hash. Quindi, anche la stringa del modello verrà divisa in blocchi 2k e verranno confrontati gli hash corrispondenti, tenendo conto che almeno k blocchi non corrispondono. In tal caso, potremmo potenzialmente scartare tutti i casi in cui il numero di disallineamenti è superiore a k. Ho capito bene?
Paresh,

kΩ(nk)O(n)

Mi piace questo approccio! Tuttavia, questo approccio è veloce in generale, ma degrada a O (mnk) se il numero di corrispondenze è elevato (O (n) corrispondenze). Tenendo presente questo, ho mantenuto due hash rotolanti, supponendo che entrambi non possano avere una collisione per lo stesso input (non l'ho fatto matematicamente poiché volevo vedere la velocità). In questo modo, non è necessario verificare una corrispondenza char-by-char se i due hash concordano. Questo è abbastanza veloce in generale, ma anche questo è lento se il numero di partite è grande. Con questo e con il modo in cui hai suggerito, è stato lento per le partite di grandi dimensioni.
Paresh,

mm/2kmO(nkm)

mm/2k2kk+1k+cΩ(nm)mm/2k
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.