7

Dato 2 stringhe s e t. Devo trovare per ogni sottostringa nella distanza di modifica s (distanza Levenshtein) a t. In realtà ho bisogno di sapere per ogni posizione i in s qual è la distanza minima di modifica per tutte le sottostringhe iniziate nella posizione i.Algoritmo per trovare la modifica di tutte le sottostringhe

Ad esempio:

t = "ab"  
s = "sdabcb" 

E ho bisogno di ottenere qualcosa di simile:

{2,1,0,2,2}

Spiegazione:

1st position: 
distance("ab", "sd") = 4 (2*subst) 
distance("ab", "sda") = 3(2*delete + insert) 
distance("ab", "sdab") = 2 (2 * delete) 
distance("ab", "sdabc") = 3 (3 * delete) 
distance("ab", "sdabcb") = 4 (4 * delete) 
So, minimum is 2 

2nd position: 
distance("ab", "da") = 2 (delete + insert) 
distance("ab", "dab") = 1 (delete) 
distance("ab", "dabc") = 2 (2*delete) 
.... 
So, minimum is 1 

3th position: 
distance("ab", "ab") = 0 
... 
minimum is 0 

e così via.

Posso usare l'algoritmo della forza bruta per risolvere questo compito, ovviamente. Ma c'è un algoritmo più veloce?

Grazie per l'aiuto.

+0

So che la tua risposta '{2,1, ** 0,2 **, 2}' è errata, perché i numeri adiacenti possono differire al massimo da 1: se c'è una sottostringa 's [i..j ] 'con la distanza minima di modifica' k' a 't', quindi la sottostringa' s [(i + 1) .. j] 'può abbinare' t' con costo al massimo 'k + 1' facendo la prima operazione di modifica un inserimento di 's [i]' all'inizio della stringa. Nel tuo esempio, per la quarta posizione, 'distanza (" ab "," b ") = 1' (1 inserto) e per la 5a,' distanza ("ab", "cb") = 1' (1 sottost) . –

risposta

4

L'algoritmo di Wagner-Fischer fornisce la risposta per tutti i prefissi "gratuitamente".

http://en.wikipedia.org/wiki/Wagner%E2%80%93Fischer_algorithm

L'ultima riga della matrice Wagner-Fischer contiene la modifica distanza da ogni prefisso di s a t.

Quindi, come prima soluzione al problema, per ogni i, eseguire Wagner-Fischer e selezionare l'elemento più piccolo nell'ultima riga.

Sarò curioso di vedere se qualcun altro sa (o può trovare) un approccio migliore.

+0

Grazie, ma intendevo questa soluzione come forza bruta ... e spero che esista una soluzione migliore (complessità temporale correlata). –

+0

Dubito che qualcuno capirà la tua risposta senza un esempio. – Elmue

3

Trovare sottostringhe in una determinata stringa è molto semplice. Si prende il normale algoritmo di Levenshtein e lo si modifica leggermente.

PRIMO: Invece di riempire la prima riga della matrice con 0,1,2,3,4,5, ... si riempie interamente con zeri. (rettangolo verde)

SECONDA: Quindi si esegue l'algoritmo.

TERZO: Invece di restituire l'ultima cella dell'ultima riga si cerca il valore più piccolo in ultima fila e restituirlo. (Rettangolo rosso)

Esempio: ago: "aba", pagliaio: "c abba c" -> risultato = 1 (conversione abba -> aba)

enter image description here

ho trovato qui: http://ginstrom.com/scribbles/2007/12/01/fuzzy-substring-matching-with-levenshtein-distance-in-python/

L'ho provato e funziona.

Questo è molto più veloce del tuo suggerimento di passare carattere per carattere attraverso la stringa come fai nella tua domanda. Crei la matrice solo una volta.

Problemi correlati