2012-02-07 7 views

risposta

10

L'algoritmo KMP ha una complessità lineare per trovare tutte le occorrenze di un modello in una stringa, come l'algoritmo Boyer-Moore¹. Se si tenta di trovare un modello come "aaaaaa" in una stringa come "aaaaaaaaa", una volta che hai la prima partita completa,

aaaaaaaaa 
aaaaaa 
aaaaaa 
    ^

tabella confine contiene le informazioni che la prossima partita più lunga possibile (corrispondente al bordo più largo del pattern) di un prefisso del pattern è solo un carattere breve (una corrispondenza completa equivale a una mancata corrispondenza oltre la fine del pattern in questo senso). Così il modello viene spostato di un luogo ulteriore, e dato dalla tabella confine è noto che tutti i caratteri del modello eccetto forse l'ultima partita, il successivo confronto è tra l'ultimo carattere del modello e il carattere di testo allineato. In questo caso particolare (trovare le occorrenze di una m in un n), che è il caso peggiore per l'algoritmo di corrispondenza ingenuo, l'algoritmo KMP confronta ogni carattere di testo esattamente una volta.

In ogni fase, almeno uno dei

  • la posizione del carattere di testo rispetto
  • la posizione del primo carattere del modello rispetto al testo

aumenta, e nessuno dei due diminuisce mai. La posizione del carattere di testo rispetto può aumentare al massimo length(text)-1 volte, la posizione del primo carattere modello può aumentare al massimo length(text) - length(pattern) volte, quindi l'algoritmo richiede al massimo 2*length(text) - length(pattern) - 1 passi.

La preelaborazione (costruzione del tavolo confine) batte al massimo 2*length(pattern) passi, così la complessità generale è O (m + n) e vengono eseguiti altri m + 2*n passaggi se m è la lunghezza del pattern e n la lunghezza il testo.

¹ Si noti che l'algoritmo di Boyer-Moore come comunemente presentato ha un caso peggiore complessità O (m * n) per i modelli di periodici e testi come un m e n se sono necessarie tutte le partite, perché dopo una corrispondenza completa,

aaaaaaaaa 
aaaaaa 
aaaaaa 
    ^
    <- <- 
^ 

l'intero modello viene ricontestualizzato. Per evitare ciò, è necessario ricordare per quanto tempo un prefisso del modello corrisponde ancora dopo il turno successivo a una corrispondenza completa e solo confrontare i nuovi caratteri.

+0

L'ho fatto. Apparentemente non abbastanza ovviamente. –

+1

Le mie scuse! Upvoted. – templatetypedef

+0

Nessun problema, si verificano equivoci. Sembra che tu abbia perso la freccia quando fai clic, però;) –

2

Potete contare funzione PI per una stringa in O(length). KMP costruisce una stringa speciale che ha lunghezza n+m+1, e conta funzione Pi su di esso, così in ogni caso complessità sarà O(n+m+1)=O(n+m)

+0

potresti fornire maggiori dettagli per favore? –

+0

è possibile controllare qui http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm – kilotaras

3

C'è un lungo articolo KMP a http://en.wikipedia.org/wiki/Knuth-morris-pratt che termina con dire

Poiché le due porzioni dell'algoritmo hanno, rispettivamente, complessità di O (k) e O (n), la complessità dell'algoritmo complessivo è O (n + k).

queste complessità sono gli stessi, indipendentemente dal numero di schemi ripetitivi sono in W o S. (fine citazione)

Quindi il costo totale di una ricerca KMP è lineare nel numero di caratteri della stringa e modello . Penso che questo vale anche se hai bisogno di trovare più occorrenze del pattern nella stringa - e se no, basti pensare alla ricerca di patternQ, dove Q è un personaggio che non si verifica nel testo, e annotando dove gli spettacoli di stato KMP che ha abbinato tutto alla Q.

+0

Questo non è molto chiaro. Diciamo che voglio usare KMP per trovare le occorrenze di "aaa" in "aaaaa", KMP non dovrebbe fare confronti n * m per trovare tutte le occorrenze? –

+0

Farebbe O (3 + 8) che significa (3 + 8) * alcuni costante – kilotaras

+0

KMP evita i confronti ricordando quanti caratteri sono stati abbinati finora. Dopo aver visto e abbinato aaa, sa che gli ultimi 3 caratteri della stringa da cercare sono aaa, quindi quando vede che questo è seguito da un altro a sa che anche questo è una corrispondenza con gli ultimi tre caratteri incluso il nuovo abbinare aaa. Questo non è nel codice di Wikipedia, che ritorna alla partita. Se usi il trucco aaaQ, KMP saprà che ha aaa , e dovrebbe andare allo stato che rappresenta aa, trovare che il carattere! = Q è un, e poi tornare allo stato aaa di nuovo. – mcdowella

Problemi correlati