Esiste una struttura di dati di "stack string" che supporta queste operazioni di stringa?


28

Sto cercando una struttura di dati che memorizza un set di stringhe su un set di caratteri Σ , in grado di eseguire le seguenti operazioni. Indichiamo D(S) come struttura dati memorizzare l'insieme di stringhe S .

  • Add-Prefix-Setsu D(S) : dato un insieme T di stringhe (possibilmente vuote), la cui dimensione è delimitata da una costante e le cui lunghezze della stringa sono delimitate da una costante, restituisce D({ts | tT,sS}) . Entrambe queste costanti delimitazione sono globali: sono uguali per tutti gli ingressi T .
  • Get-Prefixessu D(S) : restituisce . Si noti che non mi dispiace davvero quale struttura viene utilizzata per questo set, purché sia ​​possibile enumerare i suoi contenuti nel tempo .{a | asS,aΣ}O(|Σ|)
  • Remove-Prefixeson : return .D(S)D({S | un'SS,un'Σ})
  • Merge: dato e , restituisce .D(S)D(T)D(ST)

Ora, mi piacerebbe davvero fare tutte queste operazioni nel tempo , ma sto bene con una struttura che fa tutte queste operazioni nel tempo , dove è la lunghezza della stringa più lunga nel struttura. Nel caso della fusione, Vorrei una tempo di esecuzione, dove n 1 è per il primo e il per la seconda struttura.O(1)o(n)no(n1+n2)n1nn2n

Un ulteriore requisito è che la struttura sia immutabile, o almeno che le operazioni sopra riportate restituiscano strutture "nuove" in modo tale che i puntatori a quelli vecchi funzionino ancora come prima.

Una nota sull'ammortamento: va bene, ma bisogna fare attenzione alla persistenza. Dato che riutilizzo sempre le vecchie strutture, sarò nei guai se colpirò il caso peggiore con un particolare insieme di operazioni sulla stessa struttura (ignorando così le nuove strutture che crea).

Mi piacerebbe usare una tale struttura in un algoritmo di analisi su cui sto lavorando; la struttura sopra avrebbe il lookahead di cui ho bisogno per l'algoritmo.

Ho già preso in considerazione l'uso di un trie , ma il problema principale è che non so come unire i tentativi in ​​modo efficiente. Se l'insieme di stringhe per è Add-Prefix-Setcostituito solo da stringhe a carattere singolo, è possibile archiviare questi insiemi in una pila, che ti darebbe tempi di esecuzione per le prime tre operazioni. Tuttavia, questo approccio non funziona neanche per la fusione.O(1)

Infine, nota che non sono interessato ai fattori: questo è costante per tutto ciò che mi interessa.|Σ|


Le stringhe sono costruite solo dall'operazione Add-Prefix-Seto inizi con un set arbitrario di stringhe?
Joe

2
Supponiamo che prima di un'operazione di unione, v'è una stringa di lunghezza sia S e T . Come è possibile rilevare se questa stringa è duplicata in o ( n 1 + n 2 ) tempo? n1=n2STo(n1+n2)
Joe,

Inizi con un set con una stringa a carattere singolo, ma va bene anche una stringa vuota (puoi semplicemente Add-Prefix-Setinserirla)
Alex ten Brink

@Joe: questa è una buona domanda - Sto iniziando a convincermi che l'operazione di fusione praticamente rompe ogni possibilità di ottenere una tale struttura ...
Alex ten Brink

Se usi la tua rappresentazione "pila di set", potresti unire due pile in min (n1,n2)
Joe

Risposte:


5

Ho pensato per un po 'di tempo, ma non ho trovato il problema con tutte le tue operazioni nel modo più stupido possibile in una struttura DAG simile a un trie:

Add-prefisso-Set

Creare un trie di stringhe da . Collegare ciascun nodo foglia alla radice del vecchio trie.T

Complessità: O(|T|)

Merge

Unisci le radici di due strutture: crea tutti i nodi figlio del secondo figlio radice del primo nodo. Ora puoi avere più bordi contrassegnati con lo stesso carattere che vanno dallo stesso nodo.

Complessità: O(1)

Aggiornamento pigro della radice

  1. Per ogni personaggio unisci tutti i figli della radice accessibili dai bordi contrassegnati da questo carattere. ( + O ammortizzato ( 1 ) per ogni bordo mai aggiunto)O(|Σ|)O(1)
  2. Elimina tutti i bordi che vanno nella radice dall'alto. (Può succedere dopo Rimuovi prefissi, ammortizzato per ogni bordo mai aggiunto)O(1)

Get-prefissi

Lazy aggiorna il root. Ora trova tutti i figli della radice e riporta una serie di lettere sui bordi che vanno verso di loro.

Complessità: O(|Σ|)

Remove-prefissi

Lazy aggiorna il root. Unisci tutti i figli della radice e imposta il puntatore radice sul risultato di questa unione. Lazy aggiorna la nuova radice.

Complessità: + Aggiornamento pigroO(|Σ|)

Persistenza

Tutte le informazioni su questa struttura di dati possono essere salvate in array, con informazioni per nodo più informazioni O ( | Σ | ) per ogni figlio del nodo. Ogni operazione può essere svolta come serie di incarichi in questi array. Utilizzare l'albero degli intervalli persistenti o qualsiasi altra struttura di dati che può essere visualizzata come un array persistente. Moltiplicatore aggiuntivo per la memoria e la complessità dello spazio O ( l o g N ) , dove N è il numero totale di caratteri in tutte le query.O(1)O(|Σ|)O(logN)N

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.