Calcolo della sottostringa comune più lunga di due stringhe utilizzando array di suffissi


15

Dopo aver appreso come creare un array di suffissi nella complessità , sono interessato a scoprire le applicazioni degli array di suffissi. Uno di questi è trovare la sottostringa comune più lunga tra due stringhe, nel tempo O ( N ) . Ho trovato su internet il seguente algoritmo:O(N)O(N)

  1. unire le due stringhe e B in una stringa A BABAB
  2. calcola l'array di suffissi di AB
  3. calcola l' array (prefisso comune più lungo)LCP
  4. la risposta è il valore più grande LCP[i]

Ho cercato di implementarlo, ma dato che molti dettagli di implementazione non sono stati detti (cioè quando concatenando le stringhe, dovrei mettere un carattere speciale tra loro ( )?), Il mio codice ha fallito in molti casi di test. Qualcuno potrebbe elaborare di più su questo algoritmo?AcB

Grazie in anticipo.

Nota: non garantisco la correttezza di questo algoritmo; L'ho trovato su un blog e non sono sicuro che funzioni. Se ritieni che sia errato, ti preghiamo di suggerire un altro algoritmo.


3
Prima di implementare l'algoritmo, prova a capire perché funziona. Ciò potrebbe aiutare a rispondere a una domanda come come concatenare due stringhe.
Yuval Filmus,

3
Dubito della correttezza di questo algoritmo. Prendi e b c d , il modo in cui l'ho letto restituirà a b c d , che è sbagliato. abcdabcdbcdabcd
Khaur

Risposte:


20

Il tuo algoritmo non è corretto . Presumo che tu sappia come calcolare l'array di suffissi e l'array LCP di una stringa, ovvero la loro implementazione efficiente. Come è stato sottolineato nei commenti, dovresti cercare di capire cos'è ogni componente e perché funziona.

Prima di tutto, è l'array di suffissi ( ) di una stringa. Un array di suffissi è fondamentalmente tutti i suffissi della stringa S disposti in ordine lessicografico crescente. Più specificamente, il valore S A [ i ] indica che il suffisso di S a partire dalla posizione S A [ i ] è classificato i nell'ordinamento lessicografico di tutti i suffissi di S .SASSA[i]SSA[i]iS

Il prossimo è l' array L C P [ i ] indica la lunghezza del prefisso comune più lungo tra i suffissi a partire da S A [ i - 1 ] e S A [ i ] . Ossia, tiene traccia della lunghezza del prefisso comune più lungo tra due suffissi consecutivi di S se disposti in ordine lessicografico.LCPLCP[i]SA[i1]SA[i]S

Ad esempio, considera la stringa . I suffissi in ordine lessicografico sarebbero { a , a b b a b c a , a b c a , b a b c a , b b a b c a , b c a , c a } , quindi S A = [ 7 , 1S=abbabca{a,abbabca,abca,babca,bbabca,bca,ca} per un array 1 indicizzato. L'array L C P sarebbe L C P = [ - , 1 , 2 , 0 , 1 , 1 , 0 ] .SA=[7,1,4,3,2,5,6]LCPLCP=[,1,2,0,1,1,0]

Ora, data due stringhe e B , li concatenare come S = A # B , dove # è un personaggio non presente in entrambi A e B . Il motivo della scelta di un tale carattere è che, quando si calcola l'LCP di due suffissi, diciamo a b # d a b d e a b d , il confronto si interromperà alla fine della prima stringa (poiché si verifica solo una volta, due diversi suffissi non lo avranno mai nella stessa posizione) e non "overflow" nell'altra stringa.ABS=A#B#ABab#dabdabd

Ora, si può vedere che dovresti essere in grado di vedere perché hai solo bisogno di vedere valori consecutivi nell'array (l'argomento si basa sulla contraddizione e sul fatto che i suffissi in S A sono in ordine lessicografico). Continuare a controllare l' array L C P per il valore massimo in modo tale che i due suffissi confrontati non appartengano alla stessa stringa originale. Se non appartengono alla stessa stringa originale (una inizia in A e l'altra in B ), il valore più grande è la lunghezza della sottostringa comune più grande.LCPSALCPAB

Ad esempio, considera e B = b c . Quindi, S = a b c a b c # b c . I suffissi ordinati sono { a b c # b c , a b c a b c # b c , b c , b c # b c , b c aA=abcabcB=bcS=abcabc#bc . S A{abc#bc,abcabc#bc,bc,bc#bc,bcabc#bc,c,c#bc,cabc#bc}
SA=[4,1,8,5,2,9,6,3,7]LCP=[,3,0,2,2,0,1,1,0]

Ora, il massimo valore è , ma è per S A [ 1 ] e S A [ 2 ] , entrambi i quali inizia nella stringa A . Quindi, lo ignoriamo. D'altra parte, L C P [ 4 ] = 2 è per S A [ 3 ] (corrisponde al suffisso b c di B ) e S A [ 4 ]LCP[2]=3SA[1]SA[2]ALCP[4]=2SA[3]bcBSA[4](corrispondente al suffisso di A ). Quindi, questa è la sottostringa comune più lunga tra le due stringhe. Per ottenere la stringa effettiva, si prende una lunghezza 2 (valore della massima realizzabile L C P ) sottostringa partendo da entrambi S A [ 3 ] o S A [ 4 ] , che è b c .bcabc#bcA2 LCPSA[3]SA[4]bc


1
Eccellente spiegazione, ma penso che l'esempio è un po 'sbagliato, i suffissi ordinati sono: {#bc,abc#bc,abcabc#bc,bc,bc#bc,bcabc#bc,c,c#bc,cabc#bc}, SA=[7,4,1,8,5,2,9,6,3]eLCP=[−,0,3,0,2,2,0,1,1]
Saúl Martínez Vidals

1

L'algoritmo che hai trovato online non è del tutto corretto. Come menzionato da Paresh, fallirà nell'esempio da lui fornito.

Tuttavia, se si garantisce che durante il controllo dell'LCP, si controlla solo l'LCP delle sottostringhe di stringhe diverse. Ad esempio, se si trova l'LCS delle stringhe A e B, è necessario assicurarsi che le voci adiacenti dell'array di suffissi durante il controllo dell'LCP non provengano entrambe dalla stessa stringa.

Maggiori dettagli qui .


1
Quando dici "Questa risposta", intendi la tua risposta o qualche altra risposta? Utilizzare solo la casella di risposta per rispondere alla domanda, non per commentare altre risposte. Quando avrai acquisito abbastanza reputazione, sarai in grado di lasciare commenti su altre risposte.
David Richerby,

0

Penso che qualcosa come l'algoritmo che citi dovrebbe davvero funzionare se un carattere che non fa parte del set di caratteri viene utilizzato come separatore e le matrici di suffisso / prefisso sono costruite per escludere tutte le stringhe che contengono il separatore, probabilmente l'intenzione del progettista. questo è sostanzialmente equivalente alla costruzione di array di suffisso / prefisso per le due stringhe separate.

sarebbe utile per riferimento futuro se hai pubblicato un link all'algoritmo. nota che Wikipedia ha l'algoritmo per questo in pseudocodice e molti altri algoritmi. e ci sono implementazioni nella maggior parte delle lingue standard disponibili online.

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.