Esiste un algoritmo per verificare se una stringa è una catenazione di palindromi?


9

Esiste un algoritmo a tempo lineare per verificare che una sequenza di caratteri sia una concatenazione di palindromi? L'unica cosa che mi viene in mente è la soluzione ingenua:

1. k = 1
2. Split string into k substrings (all possibilities) and check
3. k++
4. repeat

Nota: la risposta è banalmente sì se le stringhe di lunghezza 1 sono definite palindromi. Supponiamo che non sia così.


14
Se stai consentendo banali palindromi di lunghezza 1 (ad esempio la stringa "a" è un palindromo), allora tutte le stringhe sono concatenazioni di palindromi.
Matt Lewis,

È utile o un esercizio?
Jan Hudec,

@MattLewis Puoi provare a ridurre al minimo il numero di palindromi. Jan, perché? Sembra un bel esercizio di programmazione dinamica.
Pål GD,

1
@Haile No. Solo palindromi disgiunti.
Saadtaame,

1
Norvig ha svolto un ampio lavoro su Palindromes. Potresti essere interessato a questa pagina: norvig.com/palindrome.html
robowolverine

Risposte:


7

Supponendo che tu voglia palindromi disgiunti, questo è noto come problema PALSTAR e esiste un algoritmo di tempo lineare di Zvi Galil e Joel Seiferas. Un algoritmo di riconoscimento on-line a tempo lineare per `` Palstar ' .

Una spiegazione dell'algoritmo è disponibile nel libro qui: Algoritmi di testo (consultare la pagina collegata e le pagine precedenti).

Se stai bene con un algoritmo quadratico temporale, la programmazione dinamica diretta sembra funzionare.

Data una stringa , manteniamo un array che ci dice se può essere scomposto in palindromi.s[1,n]s[1,j]

Manteniamo anche una tabella 2D che ci dice se è un palindromo o no. Questo possiamo costruire in tempo scegliendo un centro e spostando due puntatori verso l'esterno, verificando la presenza di palindromi con quel centro. Fallo per ogni possibile centro: centri, ognuno prendendo tempo.s[i,j]O(n2)Θ(n)O(n)

Ora, puoi controllare se può essere scomposto in palindromi, controllando per ogni se può essere decomposto, e se è un palindromo (utilizzando la tabella 2D sopra). Ciò produce un tempo e algoritmo di spazio.s[1,j+1]1ij1s[1,i]s[i+1,,j+1]Θ(n2)Θ(n2)

L'utilizzo dello spazio può essere portato fino a , se si utilizza un algoritmo on-line di Manacher per calcolare se è un palindromo (come va dal a ) , fondamentalmente eliminando la tabella 2D.O(n)s[i+1,j+1]ij11


Questo è simile al mio algoritmo, non ho spiegato la parte di preelaborazione per lasciarla come esercizio a OP, ma non so perché a nessuno importava del mio algoritmo :)

@SaeedAmiri: hai letto la prima parte della mia risposta che menziona il tempo lineare? Com'è simile? tra l'altro, OP ha cambiato la domanda per chiedere un algoritmo di tempo lineare, che rende la tua risposta e l'ultima metà della mia risposta irrilevante. Non ho cancellato quella parte dalla mia risposta, perché volevo menzionare l'algoritmo di Manacher che fa sì che l'algoritmo di programmazione dinamica usi solo lo spazio O (n) (e si sbarazza della fase di preelaborazione), e potrebbe comunque essere rilevante per altre persone che capita di imbatterti in questa domanda
Aryabhata,

Non prenderlo in serie, è solo scherzando, mi piacciono le tue risposte in generale, penso che ci sia un problema con la mia scrittura inglese, perché OP non ha capito la mia soluzione, ed era fuori dal mio umore disegnarlo per immagine . Ma il buon punto OP ha cambiato la sua domanda di recente, e potrebbe esserci una soluzione simile all'algoritmo di Manacher (ma in realtà non è facile).

1
@SaeedAmiri: Capisco, allora non preoccuparti :-)
Aryabhata,

3

Se la sovrapposizione è consentita, può essere eseguita in tempo lineare (nella dimensione della stringa di input).

Alcune definizioni

Definiamo il concetto di palindromo massimo :

Un palindromo massimo di raggio k di una stringa S è una sottostringa S 'tale che

  • partendo dal centro, S 'legge gli stessi k caratteri in entrambe le direzioni
  • ma non per k + 1 caratteri
  • k> 1 (quindi un singolo personaggio non è un palindromo)

per esempio, se S = banana, allora S' = ananaè un palindromo massimo di raggio 2.

Un palindromo massimo è un palindromo massimo di raggio k per alcuni k.

Per esempio, se S = banana, "ana", "anana", sono tutti i palindromi massime.

Usando palindromi massimi

Ora, se potessimo individuare tutti i palindromi massimi di una stringa , sarebbe semplice verificare se l'intera stringa è una concatenazione di palindromi.

Prendi S = abbaccazayaz. I suoi massimi palindromi sono:

  • abba, centrato tra la posizione 2 e 3, raggio = 2
  • acca, centrato tra le posizioni 5 e 6, raggio = 2
  • zayaz, centrato in posizione 10, raggio = 2

così "abba" si estende su [1..4], "acca" si estende su [4..7], "zayaz" si estende su [8..12]. Poiché la concatenazione di questi tre palindromi (la sovrapposizione è consentita?) Si estende su tutta la stringa, ne consegue che "abbaccazayaz" è concatenazione dei palindromi.

Calcolo dei palindromi massimi in tempo lineare

Ora, si scopre che possiamo localizzare tutti i massimi palindromi di una stringa S in tempo lineare !*

L'idea è di utilizzare un albero di suffisso per S dotato di query antenate comuni più basse a tempo costante .

Quindi possiamo verificare se una stringa S di lunghezza m è una concatenazione di palindromi nel tempo O (n).

* Gusfield, Dan (1997), "9.2 Trovare tutti i palindromi massimi nel tempo lineare", algoritmi su archi, alberi e sequenze


Supponendo che i palindromi sovrapposti siano consentiti e che stiamo cercando la sequenza palindromo più piccola, non vedo perché questo dovrebbe restituire il più piccolo (non ho un contro-esempio però). Se stiamo verificando se è possibile con palindromi di raggio almeno , allora è davvero utile. Inoltre, non è un palindromo, suppongo che tu intendessi invece. knanaanana
Khaur,

Modificato la cosa "anana", grazie. Inoltre, OP non richiede una sequenza minima di palindromi: dato che un singolo carattere non è un palindromo, dobbiamo solo decidere se la stringa di input è una concatenazione di palindromi o meno.
Haile,

1
I singoli personaggi sono palindromi (anche se poco interessanti). Se supponi che non lo siano, stai risolvendo il secondo problema che cito per . In termini di complessità, dopo aver calcolato tutti i palindromi massimi, è ancora necessario verificare che si estendano su tutta la sequenza, che IIRC impiega tempo loglineare nel numero di palindromi (che può essere quasi pari alla lunghezza della sequenza in casi patologici) . Ad ogni modo penso che dovresti enfatizzare di più che supponi che sia consentita la sovrapposizione, in quanto non è un presupposto così ovvio. k=1
Khaur,

1
@Khaur Ci vuole tempo loglinear solo se gli intervalli non sono ordinati. In questo caso probabilmente lo sono.
Yuval Filmus,

1
Nei commenti alla domanda, l'OP aggiunge esplicitamente che i palindromi sovrapposti non sono ammessi. Quindi questa soluzione nella forma attuale non è ciò che l'OP sta cercando. Penso che questa soluzione possa essere modificata per risolvere anche il caso non sovrapposto, con un po 'di pensiero e la massima complessità quadratica. Ma non ci ho pensato molto.
Paresh,

2

Supponiamo che Palindrome [] [] sia un array e Palindrome (i, j) sia una funzione che controlla se la sottostringa da i a j è palindromo e restituisce 1 se è palindromo o restituisce l'infinito se non è palindromo e stai cercando il numero più piccolo delle partizioni, crealo dal basso verso l'alto:

Palindrome[i][i]=1.
0i<j<n:Palindrome[i][j]=min{Palindrome(i,j),minik<j{Palindrome[i,k]+Palindrome[i+1,k]}}

Dovresti riempire celle e ogni cella prende al massimo quindi l'algoritmo è , con una piccola modifica (preelaborazione) puoi migliorarlo a , Inoltre trovare questa partizione non è difficile.O(n2)O(n)O(n3)O(n2)


Puoi illustrare con un esempio? Di ':abbaaccaabba.
saadtaame,

@saadtaame, OK, qui non è possibile creare una tabella (in cs.stackexchange), oppure non sono riuscito a trovare un modo per farlo, lo farò da qualche parte e inserirò qui l'immagine in seguito. ma per ora provi a capirlo da solo, inizia dalle sottostringhe di lunghezza 1, quindi controlla i palindromi di lunghezza 2, .... e così via.
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.