Trovare la sottosequenza ripetuta più lunga


9

Data una stringa , vorrei trovare la sottosequenza ripetuta (almeno due volte) più lunga. Cioè, vorrei trovare una stringa che è una sottosequenza (non deve essere contigua) di tale che . Cioè, è una stringa le cui metà appaiono due volte di seguito. Nota che è una sottosequenza di , ma non necessariamente una sottostringa.swsw=wwwws

Esempi:

Per "ababccabdc" sarà "abcabc", perché "abc" = "abc" e "abc" appaiono (almeno) due volte in "ababccabdc".

Per 'addbacddabcd' un'opzione è 'dddd' perché 'dd' appare due volte (non posso usare la stessa lettera più volte, ma qui ho 4 'd così va bene), ma è di lebngth 4. Posso trovarne una migliore di lunghezza 8: 'abcdabcd', perché 'abcd' è una sottostringa di 'addbacddabcd' che appare due volte.

Sono interessato a trovare la sottosequenza ripetuta più lunga. Questo è anche chiamato "trovare il quadrato più lungo / più grande", ma ho letto molti articoli in cui un quadrato è definito per una sottostringa e non per una sottosequenza.

Posso facilmente usare un algoritmo di forza bruta che prenderà ripetendo tutte le opzioni per un punto di interruzione nella stringa, e quindi avrò due stringhe in cui cercherò la sottosequenza comune più grande / più lunga, ma ogni controllo prenderà usando una tecnica di programmazione dinamica, quindi tutto il tempo sarà . Ho trovato un algoritmo più efficiente per la sottosequenza comune più lunga che richiede , quindi il tempo di esecuzione sarà .O(n3)O(n2)O(n3)O(n2logn)O(n3logn)

Sto cercando un algoritmo più efficiente per il problema di sottosequenza che si ripete più a lungo. Forse la mia idea di iterare su tutti i punti di interruzione fa perdere troppo tempo e può essere ridotta a meno iterazioni. O forse un algoritmo con un atteggiamento diverso può risolvere questo problema.

Ho cercato in molte riviste e domande precedenti e la maggior parte dei risultati che ho trovato riguardavano una sottostringa e non una sottosequenza.

Ho anche letto che questo può essere fatto usando gli alberi dei suffissi, ma anche questo era rilevante per le sottostringhe e non sono sicuro che una tale idea possa essere estesa per sottosequenza.

Sto cercando una soluzione che funzioni nel tempo . Se esiste uno nel tempo sarebbe ancora meglio (non sono sicuro che esista).O(n2)O(nlogn)


4
Cerca alberi di suffissi o matrici di suffissi.
Pseudonimo il

1
E 'molto improbabile che un algoritmo con tempo esiste per questo problema, dal momento che se così fosse, si potrebbe utilizzare per battere il migliore algoritmo noto per trovare la LCS di due length- stringhe e come segue: Forma la stringa , dove è copie di un carattere che non appare in o , quindi esegui l' algoritmo -time su di esso. Entrambi "metà" della più lunga sottosequenza ripetuta necessariamente iniziare con , quindi una metà viene da ciascuno di eo(n2)nuvxuxvxn+1$uvo(n2)xuv, risolvendo il problema LCS.
j_random_hacker,

@j_random_hacker LCS potrebbe essere risolto in usando Suffix Tree o in usando hash rolling. O(n+m)O(nlogn)
Evil

@Evil: Non vedo ancora come, potresti dare qualche dettaglio in più? (Sei sicuro di non pensare alla stringa secondaria comune più lunga , che può essere risolta in quelle complessità temporali?)
j_random_hacker

@j_random_hacker Ho pensato che stai confrontando la mira con LCS (consecutiva), ma qui, come hai detto, sì, non ho nemmeno visto una soluzione funzionante in n ^ 2 per Longest Common Subsequence (ho trovato un codice di programmazione dinamico, propagato su più pagine, che è difettoso, simile alla risposta declassata). Quindi semplicemente ho frainteso il tuo commento, scusa. o(n2)
Evil

Risposte:


-1

Ecco una soluzione di programmazione dinamica.

Supponiamo che la stringa di input sia . Crea una tabella cui righe e colonne sono indicizzate da (dove è la lunghezza della stringa), popolata dalla regola La risposta è .x1xnT0,,nn

T[i,j]={0if i=0 or j=0,T[i1,j1]+1if xi=xj and ij,max(T[i1,j],T[i,j1])otherwise.
T[n,n]

Supponiamo di essere in alcuni con e la condizione nella tua affermazione è vera. Quindi implica che il carattere nella posizione parte di entrambe le sottosequenze. i,ji=j+1ifdp[i][j] = dp[i - 1][j - 1] + 1i1=j
j_random_hacker il

3
Benvenuti in Informatica! Elimina il codice sorgente e sostituiscilo con idee, pseudo codice e argomenti di correttezza. Vedi qui e qui per le meta discussioni correlate.
Raffaello

@Raphael Una formula ricorsiva non conta come codice sorgente.
Numero 945

1
@BreakingBenjamin A seconda della lingua che preferisci, puoi scrivere la ricorrenza data più o meno letteralmente. Il punto è che qui non c'è spiegazione.
Raffaello
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.