Date n stringhe, una è una sottostringa di un'altra?


9

Supponiamo che ci venga data una raccolta di stringhe, . Vorrei sapere se una di queste stringhe è una sottostringa di qualsiasi altra stringa nella raccolta. In altre parole, vorrei un algoritmo per la seguente attività:S 1 , , S nnS1,...,Sn

Input:S1,...,Sn

Output: tale che è una sottostringa di e , o None se tale esistonoS i S j i j i , jio,jSiSjiji,j

Esiste un algoritmo efficiente per questo?

Se sostituiamo "sottostringa" con "prefisso", esiste un algoritmo efficiente (ordina le stringhe, quindi esegui una scansione lineare per confrontare le stringhe adiacenti; l'ordinamento assicurerà che le sottostringhe siano adiacenti). Ma sembra più difficile verificare se una stringa è una sottostringa di qualsiasi altra stringa. Un algoritmo ingenuo deve iterare su tutte le coppie , ma ciò richiede test di sottostringa . Esiste un algoritmo più efficiente?Θ ( n 2 )i,jΘ(n2)

Immagino che potremmo chiamare questo "test di sottostringa a tutte le coppie", o qualcosa del genere.

Il mio obiettivo finale è quello di potare la raccolta in modo che nessuna stringa sia una sottostringa di un'altra, rimuovendo ciascuna che è una sottostringa di qualcos'altro nella raccolta.


Suggerimento: matrice di suffissi.
Pseudonimo,

Come nota a , non è corretto se si rimuovono le sottostringhe quando le si trovano. Sarà di meno. Inoltre, è necessario ordinare per lunghezza poiché una stringa più lunga non può apparire in una stringa più corta. Ancora una volta è sbagliato qui. Θ ( n 2 )Θ(n2)Θ(n2)
Alexis Wilke,

@AlexisWilke, è corretto: questo è il numero di test di sottostringa nel caso peggiore (il caso peggiore è dove nessuna stringa è una sottostringa di un'altra). L'ordinamento per lunghezza ti dà solo un fattore due, che non influisce sugli asintotici. Θ(n2)
DW

Risposte:


6

È possibile creare un albero di suffissi in tempo lineare e verificare se esiste un nodo interno che corrisponde a una stringa completa (tempo costante per nodo).

Più in dettaglio, supponiamo che ci vengano date le stringhe .s1,,snΣ

  1. Costruisci un albero di suffissi (generalizzato) di con marcatori terminali distinti in coppia .s1$1,s2$2,,sn$nn$1,,$nΣ

    Usando l'algoritmo di Ukkonen , questo può essere fatto in tempo lineare; lineare nella somma di tutte le lunghezze di stringa.

  2. Supponendo che si etichettano le foglie con se rappresentano il suffisso di , attraversare l'albero e trovare quelle foglie etichettate , cioè le foglie che corrispondono al pieno stringhe.(i,j)si[j..|si|]sin(i,0)

    Ciò richiede un tempo lineare nella dimensione dell'albero, che a sua volta è lineare nella dimensione dell'input.

  3. Le foglie discendenti del genitore di (che è raggiunto da un bordo etichettato ) rappresentano tutte le partite dal set; ciò deriva dall'invariante di base degli alberi di suffisso. Trova una corrispondenza scendendo a qualsiasi foglia (ma ).(i,0)$i(i,0)

    Questo richiede di nuovo tempo lineare.

I marcatori terminali distinti non sono realmente necessari; una sola utilizzata per terminare tutte le stringhe è abbastanza sufficiente purché si consentano più etichette per foglia.

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.