palindrom træ | |||||||
---|---|---|---|---|---|---|---|
engelsk træ | |||||||
| |||||||
Type | datastruktur | ||||||
Opfindelsens år | 2015 | ||||||
Forfatter | Mikhail Rubinchik [d] | ||||||
Kompleksitet i O-symboler | |||||||
|
|||||||
Mediefiler på Wikimedia Commons |
Et palindromisk træ ( eng. palindromic tree , også overtree [1] , eng. eertree ) er en datastruktur designet til at lagre og behandle palindromiske delstrenge af en streng . Det blev foreslået af forskere fra Ural Federal University Mikhail Rubinchik og Arseny Shur i 2015. Repræsenterer to præfikstræer , samlet fra højre "halvdele" af palindromiske understrenge af henholdsvis lige og ulige længder. Strukturen optager hukommelse og kan bygges i tid , hvor er længden af strengen, og er antallet af forskellige tegn i den. Ved hjælp af et palindromtræ kan man effektivt løse sådanne problemer som at tælle antallet af forskellige palindromiske delstrenge, finde opdelingen af en streng i det mindste antal palindromer, kontrollere om en delstreng er et palindrom og andre.
Lad være en streng og være den omvendte streng . Når palindromtræet i en streng beskrives , bruges følgende notation [2] :
I notationen ovenfor er palindromtræet i en streng en rettet graf , hvor hvert toppunkt svarer til og er identificeret med et unikt subpalindrom af strengen. Hvis strengen har subpalindromer og , hvor er en eller anden alfabetisk karakter , så har palindromtræet en bue markeret med symbolet , fra toppunktet svarende til , til toppunktet svarende til . I en sådan graf kan ethvert toppunkt kun have én indkommende bue. For nemheds skyld introduceres også to hjælpespidser, som svarer til henholdsvis længdepalindromer ( tom streng ) og ("imaginær" streng. Buer fra den tomme streng fører til toppunkter svarende til palindromer af formen , og fra den "imaginære streng" til toppunkter svarende til palindromer af formen (det vil sige bestående af et enkelt tegn). Et vertex kaldes selv hvis det har et lige længde palindrom, og ellers ulige . Det følger af definitionen, at buer i et palindromtræ kun passerer mellem hjørner med samme paritet. Fra et præfikstræs synspunkt kan denne struktur beskrives som følger [3] :
Toppunkterne og buerne på palindromtræet danner to præfikstræer, hvis rødder er placeret ved de hjørner, der definerer henholdsvis de tomme og "imaginære" strenge. I dette tilfælde er det første præfikstræ sammensat af de højre halvdele af subpalindromer af lige længde, og det andet af ulige. |
Antallet af toppunkter i palindromtræet overstiger ikke , hvilket er en direkte konsekvens af følgende lemma [4] :
En længdestreng kan højst have distinkte ikke-tomme palindromiske understrenge. Efter at have tildelt et bestemt tegn til slutningen af en streng, kan antallet af forskellige subpalindromer i denne streng desuden ikke stige med mere end . |
Denne erklæring følger af følgende fakta:
Den sidste egenskab svarer i det væsentlige til lemmaet, da alle nye understrenge, der dukker op, når det næste tegn tilføjes til strengen, skal være dets suffikser [5] . ■
Ud over de sædvanlige buer, der tjener som overgange for præfikstræet, er der for hvert vertex af palindromtræet defineret et suffiksled , der fører fra toppunktet til toppunktet svarende til det største egentlige (ikke lig med hele strengen ) suffiks palindrom . Samtidig er suffiksleddet fra det "imaginære" toppunkt ikke defineret, men per definition fører det fra et tomt toppunkt til det "imaginære". Suffiksled danner et træ med rod i et "imaginært" toppunkt og spiller en vigtig rolle i konstruktionen af et palindromtræ [3] .
Som mange andre strengstrukturer er et palindromtræ bygget iterativt . I starten består den kun af toppunkter svarende til de tomme og imaginære strenge. Strukturen genopbygges derefter gradvist, efterhånden som strengen vokser et tegn ad gangen. Da der højst dukker ét nyt palindrom op i en streng, når man tilføjer ét tegn, vil genopbygning af træet i værste fald kræve tilføjelse af én ny node og et suffikslink til det. For at bestemme en mulig ny knude under trækonstruktion, opretholdes en sidste pointer til knudepunktet svarende til det største af de nuværende palindrom-suffikser [3] .
Alle suffiks-palindromer i strengen kan nås med suffikslinks fra sidste , så for at bestemme et nyt suffiks-palindrom (det vil svare til det nye toppunkt, hvis nogen) er det nødvendigt at følge suffiksleddet fra sidste , indtil det konstateres, at tegnet, der går forud for det aktuelle suffiks-palindrom , matcher det tegn, der blev tildelt strengen. Mere formelt, lad være strengens maksimale palindrom-suffiks , så enten , eller , hvor er et eller andet palindrom-suffiks . Således itererer man blandt suffikslinkene i last , kan man afgøre, om det kan udvides til ved at sammenligne tegnene og . Når det tilsvarende palindrom-suffiks er fundet, bør du kontrollere, om palindromtræet indeholder en overgang fra det tilsvarende toppunkt ved symbolet [3] .
Hvis der er en sådan overgang, er den allerede stødt på i linjen tidligere og svarer til det toppunkt, som denne overgang fører til. Ellers skal du oprette et nyt toppunkt til det og lave en overgang fra . Dernæst skal du definere et suffikslink for , der matcher det næstlængste palindrom-suffiks . For at finde det, bør man fortsætte med at omgå de sidste suffiksforbindelser, indtil det andet vertex stødes på , sådan at ; det er dette toppunkt, der vil være suffikslinket . Hvis vi betegner overgangen fra toppen med symbol som , kan hele processen beskrives med følgende pseudokode [3] :
find_link(v)-funktion: mens s k -len(v)-1 ≠ s k : assign v = link(v) return v funktion add_letter(c): tildel k = k + 1 definer s k = c definer q = find_link(sidste) hvis δ(q, c) ikke er defineret: definer p = new_vertex() definer len(p) = len(q ) + 2 definere link(p) = δ(find_link(link(q)), c) definere δ(q, c) = p tildele sidste = δ(q, c)Det antages her, at træet i første omgang kun er beskrevet af to toppunkter med længder og følgelig med en suffiksforbindelse fra det første toppunkt til det andet. Variablen sidst gemmer toppunktet svarende til det største suffiks palindrom af den aktuelle linje, indledningsvis peger det på toppunktet på den nulte linje. Det antages også, at det oprindeligt er lig med, og der er skrevet et eller andet tjenestetegn ind, som ikke forekommer i strengen .
Kompleksiteten af algoritmen kan variere afhængigt af de datastrukturer, der lagrer springtabellen i træet. I det generelle tilfælde, når du bruger et associativt array , når den tid, der bruges på at få adgang , , hvor er størrelsen på det alfabet, som strengen er bygget af. Det er værd at bemærke, at hver iteration af det første kald til find_link reducerer længden af last , og af den anden, længden af link(last) , som kun kan øges med én mellem successive kald til add_letter . Den samlede tid for find_link overstiger således ikke , og den samlede tid, der kræves for at udføre add_letter- kald , kan estimeres til [3] . Hukommelsesforbruget af denne struktur er lineært i værste fald, men hvis vi betragter strukturens gennemsnitlige størrelse over alle strenge af en given længde , vil det gennemsnitlige hukommelsesforbrug være i størrelsesordenen [6] .
Samtidig med introduktionen af denne datastruktur foreslog Rubinchik og Shur også en række modifikationer, der gør det muligt at udvide omfanget af opgaver løst af et palindromtræ. Især blev der foreslået en metode, der gør det muligt at konstruere et generelt palindromtræ for et sæt strenge med de samme asymptoter . En sådan modifikation giver os mulighed for at løse de samme problemer, der betragtes i sammenhæng med et sæt strenge - for eksempel at finde det største fælles subpalindrom af alle strenge eller antallet af forskellige subpalindromer af alle strenge i aggregatet. En anden foreslået ændring var en variant af trækonstruktion, hvor tilføjelsen af et tegn tager tid i værste fald (og ikke amortiseres , som det sker i standardkonstruktionen) og hukommelse. Denne tilgang gør det muligt at give delvis persistens af træet, hvor det er muligt at rulle tilføjelsen af det sidste tegn tilbage på vilkårlige tidspunkter. Derudover blev der foreslået en fuldt persistent version af træet, som giver dig mulighed for at få adgang til og tilføje et tegn til enhver af de tidligere gemte versioner i tid og hukommelse i værste fald [7] .
I 2019 udviklede Watanabe og kolleger en datastruktur baseret på et palindromtræ, kaldet e 2 rtre 2 , til at arbejde med subpalindromer af strenge givet ved run- length- kodning [4] , og i 2020, det samme team af forfattere, sammen med Mieno udviklede to algoritmer, der gør det muligt at opretholde et palindromtræ på et glidende vindue af størrelse . Den første af disse algoritmer kræver tid og hukommelse, og den anden kræver tid og hukommelse [8] .
Palindromtræet giver mange mulige anvendelsesmuligheder til at opnå teoretisk hurtige og praktisk taget let implementerede algoritmer til løsning af en række kombinatoriske problemer inden for programmering og matematisk kybernetik [9] .
En af de opgaver, som denne struktur blev udviklet til, er at tælle forskellige subpalindromer i en streng online . Det kan indstilles som følger: Et tegn ad gangen tildeles et tegn ad gangen til den oprindeligt tomme streng. Ved hvert trin skal du udskrive antallet af forskellige subpalindromer i den givne streng. Fra palindromtræets synspunkt svarer dette til at udskrive antallet af ikke-trivielle hjørner i strukturen ved hvert trin. En lineær løsning til offlineversionen af dette problem blev præsenteret i 2010 [10] , og den optimale løsning med eksekveringstid for onlineversionen blev fundet i 2013 [11] . Den angivne løsning brugte dog to "tunge" datastrukturer - en analog af Manaker-algoritmen samt et suffikstræ . Palindromtræet har på den ene side samme asymptotik i værste fald, og på den anden side er det en meget mere let struktur [3] .
En anden mulig anvendelse af denne struktur er opregningen af palindromrige binære strenge [12] . Tidligere blev det vist, at et ord af længde ikke kan indeholde mere end forskellige palindromer; ord, som dette skøn opnås på, kaldes palindrom-rige. Begrebet palindromiske ord blev introduceret af Amy Glen og kolleger i 2008 [13] . Rubinchik og Shur viste, at man ved hjælp af et palindromtræ kan detektere alle palindromiske ord, hvis længde ikke overstiger , hvor er antallet af sådanne ord. Dette resultat gjorde det muligt at øge antallet af kendte medlemmer af A216264 -sekvensen i OEIS fra 25 til 60. De opnåede data viste, at sekvensen vokser meget langsommere end tidligere antaget, nemlig at den er afgrænset ovenfra som [14] .
Strenge | |
---|---|
String lighedsmål | |
Understrengssøgning | |
palindromer | |
Sekvensjustering | |
Suffiksstrukturer | |
Andet |