arbore palindrom | |||||||
---|---|---|---|---|---|---|---|
Engleză copac | |||||||
arbore palindrom pentru string eertree | |||||||
Tip de | structură de date | ||||||
Anul inventiei | 2015 | ||||||
Autor | Mihail Rubinchik [d] | ||||||
Complexitatea în simbolurile O | |||||||
|
|||||||
Fișiere media la Wikimedia Commons |
Un arbore palindromic ( eng. palindromic tree , de asemenea overtree [1] , eng. eertree ) este o structură de date concepută pentru a stoca și procesa subșiruri palindromice ale unui șir . A fost propus de oamenii de știință de la Universitatea Federală Ural Mikhail Rubinchik și Arseny Shur în 2015. Reprezintă doi arbori de prefix , asamblați din „jumătățile” din dreapta ale subșirurilor palindromice de lungime pară și, respectiv, impară. Structura ocupă memorie și poate fi construită în timp , unde este lungimea șirului și este numărul de caractere diferite din acesta. Cu ajutorul unui arbore palindrom, se pot rezolva în mod eficient probleme precum numărarea numărului de subșiruri palindromice diferite, găsirea împărțirii unui șir în cel mai mic număr de palindrom, verificarea dacă un subșir este un palindrom și altele.
Să fie un șir și să fie șirul inversat . Când descriem arborele palindrom al unui șir , se utilizează următoarea notație [2] :
În notația de mai sus, arborele palindrom al unui șir este un grafic direcționat , fiecare vârf al căruia îi corespunde și este identificat cu un subpalindrom unic al șirului. Dacă șirul are subpalindromuri și , unde este vreun caracter alfabetic , atunci arborele palindrom are un arc marcat cu simbolul , de la vârful corespunzător lui , până la vârful corespunzător lui . Într-un astfel de grafic, orice vârf poate avea doar un arc de intrare. Pentru comoditate, sunt introduse și două vârfuri auxiliare, care corespund palindromurilor de lungime ( șir goală ) și respectiv șir („imaginar”). Arcurile din șirul gol conduc la vârfuri corespunzătoare palindromurilor de forma , iar din „șirul imaginar” la vârfuri corespunzătoare palindromurilor formei (adică formate dintr-un singur caracter). Un vârf este numit chiar dacă are un palindrom de lungime pară, iar în caz contrar impar . Din definiție rezultă că arcurile dintr-un arbore palindrom trec numai între vârfuri cu aceeași paritate. Din punctul de vedere al arborilor de prefix, această structură poate fi descrisă după cum urmează [3] :
Vârfurile și arcurile arborelui palindrom formează doi arbori de prefix ale căror rădăcini sunt situate la vârfurile care definesc șirurile goale, respectiv „imaginare”. În acest caz, primul arbore de prefix este compus din jumătățile drepte ale subpalindromurilor de lungime pară, iar al doilea din cele impare. |
Numărul de vârfuri din arborele palindrom nu depășește , ceea ce este o consecință directă a următoarei leme [4] :
Un șir de lungime poate avea cel mult subșiruri palindromice nevide distincte. Mai mult, după atribuirea unui anumit caracter la sfârșitul unui șir, numărul de subpalindromuri diferite ale acestui șir poate crește cu cel mult . |
Această afirmație rezultă din următoarele fapte:
Ultima proprietate este în esență echivalentă cu lema, deoarece toate subșirurile noi care apar la adăugarea următorului caracter la șir trebuie să fie sufixele acestuia [5] . ■
Pe lângă arcurile obișnuite care servesc drept tranziții pentru arborele de prefix, pentru fiecare vârf al arborelui palindrom este definită o legătură sufixă care duce de la vârf la vârful corespunzător celui mai mare sufix propriu (nu este egal cu întregul șir). palindrom . În același timp, legătura sufixului de la vârful „imaginar” nu este definită, dar prin definiție duce de la un vârf gol la cel „imaginar”. Legăturile sufixelor formează un arbore înrădăcinat la un vârf „imaginar” și joacă un rol important în construcția unui arbore palindrom [3] .
La fel ca multe alte structuri de șir, un arbore palindrom este construit iterativ . Inițial, este format doar din vârfuri corespunzătoare șirurilor goale și imaginare. Structura este apoi reconstruită treptat pe măsură ce șirul crește câte un caracter. Deoarece cel mult un nou palindrom apare într-un șir la adăugarea unui caracter, reconstruirea arborelui în cel mai rău caz va necesita adăugarea unui nou nod și a unei legături de sufix la acesta. Pentru a determina un posibil nou nod în timpul construcției arborelui, se menține un ultim indicator către nodul corespunzător celui mai mare dintre sufixele palindromului actual [3] .
Toate sufixele-palindromele șirului sunt accesibile prin legături sufixe de la last , așa că pentru a determina un nou sufix-palindrom (va corespunde noului vârf, dacă există) este necesar să urmați legăturile sufixe ale ultimului până se constată că caracterul care precede sufixul-palindrom curent se potrivește cu caracterul care a fost atribuit șirului. Mai formal, fie sufixul maxim palindrom al șirului , apoi fie , fie , unde este un sufix palindrom . Astfel, iterând printre legăturile sufixe ale lui last , se poate determina dacă acesta poate fi extins prin compararea caracterelor și . Când a fost găsit sufixul palindrom corespunzător , ar trebui să verificați dacă arborele palindrom conține o tranziție de la vârful corespunzător prin simbolul [3] .
Dacă există o astfel de tranziție, atunci aceasta a fost deja întâlnită în linie mai devreme și corespunde vârfului la care duce această tranziție. În caz contrar, trebuie să creați un nou vârf pentru acesta și să faceți o tranziție de la . Apoi, definiți o legătură de sufix pentru care se potrivește cu al doilea cel mai lung sufix palindrom . Pentru a-l găsi, ar trebui să continuați să ocoliți ultimele legături sufixe până când este întâlnit al doilea vârf , astfel încât ; acest vârf va fi legătura sufixului . Dacă notăm tranziția de la vârf prin simbol ca , întregul proces poate fi descris prin următorul pseudocod [3] :
Funcția find_link(v): în timp ce s k -len(v)-1 ≠ s k : atribuiți v = link(v) return v funcția add_letter(c): atribuiți k = k + 1 define s k = c define q = find_link(last) dacă δ(q, c) nu este definit: define p = new_vertex() define len(p) = len(q ) + 2 definesc link(p) = δ(find_link(link(q)), c) defines δ(q, c) = p atribui ultimul = δ(q, c)Se presupune aici că inițial arborele este descris doar de două vârfuri cu lungimi și, în consecință, cu o legătură sufixă de la primul vârf la al doilea. Ultima variabilă stochează vârful corespunzător celui mai mare sufix palindrom al liniei curente, inițial indică vârful liniei zero. De asemenea, se presupune că inițial este egal cu și în care este scris un caracter de serviciu, care nu apare în șirul .
Complexitatea algoritmului poate varia în funcție de structurile de date care stochează tabelul de salt în arbore. În cazul general, când se folosește o matrice asociativă , timpul petrecut pentru accesare ajunge la , unde este dimensiunea alfabetului din care este construit șirul. Este de remarcat faptul că fiecare iterație a primului apel la find_link reduce lungimea last , iar a celui de-al doilea, lungimea link(last) , care poate crește doar cu unul între apelurile succesive la add_letter . Astfel, timpul total al find_link nu depășește , iar timpul total necesar pentru a executa apelurile add_letter poate fi estimat ca [3] . Consumul de memorie al acestei structuri este liniar în cel mai rău caz, totuși, dacă luăm în considerare dimensiunea medie a structurii pe toate șirurile de o lungime dată , consumul mediu de memorie va fi de ordinul [6] .
Concomitent cu introducerea acestei structuri de date, Rubinchik și Shur au propus și o serie de modificări care permit extinderea domeniului de aplicare a sarcinilor rezolvate de un arbore palindrom. În special, a fost propusă o metodă care permite construirea unui arbore palindrom general pentru un set de șiruri cu aceleași asimptotice . O astfel de modificare ne permite să rezolvăm aceleași probleme considerate în contextul unui set de șiruri - de exemplu, să găsim cel mai mare subpalindrom comun dintre toate șirurile sau numărul de subpalindromuri diferite ale tuturor șirurilor în agregat. O altă modificare propusă a fost o variantă de construcție a arborelui, în care adăugarea unui caracter necesită timp în cel mai rău caz (și nu amortizată , așa cum se întâmplă în construcția standard) și memorie. Această abordare face posibilă asigurarea persistenței parțiale a arborelui, în care este posibil să se anuleze adăugarea ultimului caracter în momente arbitrare. În plus, a fost propusă o versiune complet persistentă a arborelui, care vă permite să accesați și să adăugați un caracter la oricare dintre versiunile salvate anterior în timp și memorie în cel mai rău caz [7] .
În 2019, Watanabe și colegii au dezvoltat o structură de date bazată pe un arbore palindrom, numit e 2 rtre 2 , pentru a lucra cu subpalindromuri de șiruri date prin codificare run-length [4] , iar în 2020, aceeași echipă de autori, împreună cu Mieno, a dezvoltat doi algoritmi, care să permită menținerea unui arbore palindrom pe o fereastră glisantă de dimensiune . Primul dintre acești algoritmi necesită timp și memorie, iar al doilea necesită timp și memorie [8] .
Arborele palindrom oferă numeroase aplicații posibile pentru obținerea de algoritmi teoretic rapid și practic ușor de implementat pentru rezolvarea unui număr de probleme combinatorii în programare și cibernetică matematică [9] .
Una dintre sarcinile pentru care a fost dezvoltată această structură este de a număra diferite subpalindromuri într-un șir online . Poate fi setat după cum urmează: câte un caracter i se atribuie câte un caracter șirului inițial gol. La fiecare pas, trebuie să imprimați numărul de subpalindromuri diferite din șirul dat. Din punctul de vedere al arborelui palindrom, aceasta este echivalentă cu tipărirea numărului de vârfuri non-triviale din structură la fiecare pas. O soluție liniară pentru versiunea offline a acestei probleme a fost prezentată în 2010 [10] , iar soluția optimă cu timp de execuție pentru versiunea online a fost găsită în 2013 [11] . Cu toate acestea, soluția indicată a folosit două structuri de date „greu” - un analog al algoritmului Manaker , precum și un arbore de sufixe . Arborele palindrom, pe de o parte, are aceleași asimptotice în cel mai rău caz, iar pe de altă parte, este o structură mult mai ușoară [3] .
O altă posibilă aplicație a acestei structuri este enumerarea șirurilor binare bogate în palindrom [12] . Mai devreme s-a arătat că un cuvânt de lungime nu poate conține mai mult decât palindromuri diferite; cuvintele pe care se realizează această estimare sunt numite bogate în palindrom. Conceptul de cuvinte bogate în palindromic a fost introdus de Amy Glen și colegii săi în 2008 [13] . Rubinchik și Shur au arătat că folosind un arbore palindrom, se pot detecta toate cuvintele bogate în palindromic a căror lungime nu depășește , unde este numărul acestor cuvinte. Acest rezultat a făcut posibilă creșterea numărului de membri cunoscuți ai secvenței A216264 în OEIS de la 25 la 60. Datele obținute au arătat că secvența crește mult mai lent decât se credea anterior, și anume, este mărginită de sus ca [14] .
Siruri de caractere | |
---|---|
Măsuri de similitudine a șirurilor | |
Căutare subșir | |
palindromuri | |
Alinierea secvenței | |
Structuri de sufix | |
Alte |