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,jSiSji≠ji,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.