2016-01-19 10 views
6

Dato una stringa s di lunghezza n, è possibile contare il numero di sottostringhe distinte in s in O (n)?È possibile contare il numero di sottostringhe distinte in una stringa in O (n)?

Esempio

ingresso: abb

uscita: 5 ('abb', 'ab', 'bb', 'a', 'b')

Ho fatto qualche ricerca, ma io non riesco a trovare un algoritmo che risolve questo problema in un tale maniera efficiente. So che un approccio O (n^2) è possibile, ma esiste un algoritmo più efficiente?

Non è necessario ottenere ciascuna delle sottostringhe, ma solo il numero totale di distinte (nel caso in cui faccia la differenza).

+0

'ba' non è una sottostringa di abb. – gnasher729

+0

@ gnasher729 hai ragione, qualcuno lo ha già modificato. – donrondon

+0

Penso che questa domanda dovrebbe essere qui: https://cs.stackexchange.com/ – ChaosPredictor

risposta

8

È possibile utilizzare l'algoritmo di Ukkonen per costruire un albero suffisso nel tempo lineare:

https://en.wikipedia.org/wiki/Ukkonen%27s_algorithm

Il numero di stringhe di s è allora il numero di prefissi di stringhe nel trie, che è possibile calcolare semplicemente in tempo lineare. È solo il numero totale di personaggi in tutti i nodi.

Per esempio, il vostro esempio produce un albero suffisso come:

  /\     
      b a 
      | b 
      b b 

5 caratteri nella struttura, in modo da 5 stringhe. Ogni stringa univoca è un percorso dalla radice che termina dopo una lettera diversa: abb, ab, a, bb, b. Quindi il numero di stringhe è il numero di lettere nell'albero.

Più precisamente:

  • Ogni stringa è il prefisso di alcuni suffisso della stringa;
  • Tutti i suffissi sono nel trie;
  • Quindi c'è una corrispondenza di 1-1 tra sottostringhe e percorsi attraverso il trie (dalla definizione di trie); e
  • esiste una corrispondenza tra 1-1 lettere nei viali e non vuoti, perché:
    • ogni percorso non vuoto distinta termina in una posizione distinta dopo l'ultima lettera; e
    • il percorso per la posizione dopo ogni lettera è unico

NOTA per le persone che si stanno chiedendo come potrebbe essere possibile costruire un albero che contiene (N^2) caratteri O a O (N) tempo:

C'è un trucco per la rappresentazione di un albero di suffisso. Invece di memorizzare le stringhe reali nei nodi dell'albero, basta semplicemente memorizzare i puntatori nella stringa originale, quindi il nodo che contiene "abb" non ha "abb", ha (0,3) - 2 interi per nodo, indipendentemente dalla lunghezza della stringa in ciascun nodo e l'albero del suffisso ha nodi O (N).

+0

Grazie per la tua risposta. L'articolo di wikipedia cui si è fatto riferimento afferma che l'algoritmo di Ukkonen raggiunge il tempo O (n), ma solo per alfabeti di dimensioni costanti, cosa significa? Inoltre, non capisco perché il numero di sottostringhe di 's' sia il" numero totale di caratteri in tutti i nodi "(dell'albero risultante di Ukkonen). – donrondon

+0

"alfabeti a dimensione costante" significa che ci sono un numero limitato di caratteri tra cui scegliere nella stringa, come 26 lettere, o 256 byte, o 65536 caratteri, ecc. L'alternativa è alberi di suffisso per sequenze su alfabeti infiniti come numeri interi illimitati arbitrari . –

+0

Ho aggiunto alcune spiegazioni per rispondere alla tua altra domanda –

2

Costruire il LCP array e sottrarre la sua somma dal numero di sottostringhe (n (n + 1)/2).

+0

Potresti spiegare come costruire l'array LCP in O (n) ?, ho trovato alcune informazioni a riguardo, ma sono un po ' un po 'perso. – donrondon

+0

@donrondon Hai un albero di suffisso? –

+0

So come crearne uno in O (n^2), ma non in O (n). – donrondon

Problemi correlati