Suffix automat | |||||||
---|---|---|---|---|---|---|---|
engelsk suffix automat riktad acyklisk ordgraf | |||||||
| |||||||
Sorts | Substring index | ||||||
Uppfinningens år | 1983 | ||||||
Författare | Anselm Bloomer, Janet Bloomer, Andrzej Ehrenvecht , David Haussler , Ross McConnell | ||||||
Komplexitet i O-symboler | |||||||
|
|||||||
Mediafiler på Wikimedia Commons |
Suffix automaton ( engelska suffixet automaton , riktad acyklisk ordgraf ) är en datastruktur som låter dig lagra i komprimerad form och bearbeta information associerad med delsträngar av en given sträng. Representerar en deterministisk finit automat som accepterar alla suffix av ett ord och endast dem, och har minsta möjliga antal tillstånd bland alla sådana automater. Mindre formellt är en suffixautomat en riktad acyklisk graf med en distingerad initial någonsymbolernaär märkta medbågaroch en uppsättning "slutliga" hörn,vertex sammanfogas , bildar ett givet suffix. Av alla grafer som uppfyller denna beskrivning är suffixet automat den som har minsta möjliga antal hörn .
Suffixet automat beskrevs först av en grupp forskare från University of Denver och Colorado 1983, de visade också att storleken på automaten beror linjärt på längden och föreslog också en onlinealgoritm för att bygga den med en linjär gångtid . I ytterligare arbeten om detta ämne upptäcktes en nära koppling mellan suffixautomaten och suffixträden , och konceptet med suffixautomaten fick olika generaliseringar. Således introducerades en komprimerad suffixautomat, erhållen från den ursprungliga genom en procedur liknande den som tillämpades på ett suffix bor för att få ett suffixträd, samt en generaliserad suffixautomat, som är byggd för en uppsättning ord och accepterar ord som är suffix till minst en av uppgifterna .
Med hjälp av en suffixautomat kan du effektivt lösa sådana problem som att söka efter en delsträng i en sträng , bestämma den största gemensamma delsträngen av två eller flera strängar och andra .
Konceptet med en suffixautomat introducerades av en grupp forskare från University of Denver och Colorado Anselm Blumer, Andrzej Ehrenvecht , David Haussler , Ross McConnell och Janet Bloomer 1983, även om strukturer relaterade till det påträffades tidigare i arbetet av Peter Weiner [1] , Vaughn Pratt [2] och Anatoly Olesevich Slisenko [3] ägnade sig åt algoritmer för att konstruera suffixträd . I samma arbete visade Bloomer och andra att en automat konstruerad av ett ord som är längre än det inte innehåller fler tillstånd och inga fler övergångar, och presenterade även en linjär algoritm för att konstruera en automat [4] .
1983 utvecklade Mu Tian Chen och Joel Seiferas oberoende en algoritm för att konstruera en suffixautomat som visar att Weiners algoritm [1] som föreslogs 1973 för att konstruera ett ordsuffixträd också konstruerar en suffixautomat för det omvända ordet som en hjälpstruktur [5] . 1987 beskrev Bloomer och andra, i analogi med ett suffixträd, en komprimerad suffixautomat [6] erhållen från en suffixautomat genom att ta bort icke-slutliga tillstånd med ett utfallshalvgrad lika med ett, och 1997 Maxime Crochemore och Renaud Verin utvecklade en linjär algoritm för dess direkta konstruktion [7] . År 2001 utvecklade Shunsuke Inenaga och andra en linjär onlinealgoritm för att konstruera en komprimerad suffixautomat [8] , såväl som en linjär algoritm för att konstruera en komprimerad suffixautomat för en uppsättning ord som ges av ett prefixträd [9] .
I sin ursprungliga artikel definierade Bloomer och kollegor strukturen de beskrev som en minimal automat som känner igen alla delsträngar (inte suffix) för ett givet ord. De kallade denna struktur en riktad acyklisk ordgraf [ 4 ] . Därefter användes detta namn också som en synonym för en deterministisk acyklisk finit automat - en minimal automat som känner igen en godtycklig finit uppsättning ord (som inte nödvändigtvis utgör en uppsättning av suffix eller delsträngar av en viss sträng) [10] [ 11] .
När man beskriver suffixautomater och relaterade fakta och satser används ofta notationer från teorin om formella språk i allmänhet och automatteori i synnerhet [12] :
Formellt definieras en deterministisk finit automat av en uppsättning av fem element där:
Oftast, i praktiken, representeras ändliga automater som en riktad graf ( diagram ) så att [13] :
I en sådan graf identifieras hörn och bågar med tillstånd respektive övergångar för automaten. Automaten accepterar ett ord om och endast om det finns en väg från det initiala tillståndet till något slutligt tillstånd , så att om vi sammanfogar symbolerna som påträffas på denna väg får vi ordet . Den uppsättning ord som en automat accepterar utgör språket för denna automat [12] .
Den rätta kontexten för ett ord i förhållande till språket kallas mängden . Det vill säga, detta är en uppsättning ord , som tillskriver som till ordet till höger resulterar i ett ord från språket . Rätt sammanhang inducerar en naturlig ekvivalensrelation på mängden av alla ord. Om ett språk kan definieras av någon deterministisk finit automat, så finns det för det en unik, upp till isomorfism , automat, som samtidigt har minsta möjliga antal tillstånd. En sådan automat kallas minimal för ett givet språk , Myhill-Nerode-satsen tillåter oss att specificera det explicit [14] [15] :
En minimal automat som känner igen ett språk över ett alfabet kan ges enligt följande:
|
I en sådan notation är en suffixautomat en minimal DFA som accepterar ordet suffixspråk . Rätt sammanhang för ett ord relativt ett givet språk består av ord som - suffix . Detta tillåter oss att formulera följande lemma, som definierar en en-till-en-överensstämmelse mellan rätt kontext för ett ord och uppsättningen positioner för dess förekomster i som ett underord [16] [17] :
Låta vara uppsättningen av rätt positioner av förekomster i . Mellan elementen i uppsättningarna och det finns följande en-till-en-korrespondens:
|
Till exempel för ett ord och dess underord och . Informellt består det av ord som följer förekomster till slutet av ordet, och - från positionerna för dessa förekomster. I det här exemplet matchar elementet ordet . Samtidigt motsvarar elementet ordet .
Av detta följer ett antal strukturella egenskaper hos tillstånden för suffixautomaten och orden som de accepterar. Låt , sedan [17] :
Således accepterar vilket tillstånd som helst av suffixautomaten någon kontinuerlig kedja av kapslade suffix av den största strängen från detta tillstånd [17] .
Den vänstra förlängningen av en sträng är den längsta strängen som har samma högra kontext som . Längden på den längsta strängen som accepteras av staten betecknas som . Det är sant för honom att [18] :
Den vänstra förlängningen av en sträng kan representeras som , där är det längsta ordet så att varje förekomst av ett ord i föregås av ordet . |
En suffixlänk från ett tillstånd är en pekare till det tillstånd som innehåller det största suffixet som inte accepteras av staten .
I denna notation kan vi säga att staten tar exakt alla suffix som är längre än och inte längre än . Dessutom är följande sant [18] :
Suffixlänkar bildar ett träd , som kan anges uttryckligen enligt följande: |
Ett prefixträd (eller borrning ) är ett rotorienterat träd , vars bågar är markerade med symboler på ett sådant sätt attinte mer än en båge kommer ut från någon vertex av detta träd , märkt med en given symbol. Vissa hörn i prefixträdet är märkta. Ett prefixträd sägs definiera en uppsättning ord som definieras av vägar från trädets rot till märkta hörn. Prefixträd är alltså en speciell sorts finita automater, om vi betraktar roten som initialtillståndet och de märkta hörnen som sluttillstånden [19] . Suffixet bor för ett ordär ett prefixträd som definierar språket för suffixen för detta ord. Ett suffixträd är ett träd som erhålls från ett suffixhål genom en kompressionsprocedur, där successiva kanter limmas ihop om det finns en icke-slutlig vertex mellan dem, vars grad är 2 [18] .
Per definition kan en suffixautomat erhållas genom att minimera ett suffixhål. Dessutom kan en komprimerad suffixautomat erhållas både genom att minimera ett suffixträd (förutsatt att alfabetets symboler är ord på trädets kanter), och genom att komprimera en konventionell automat [8] . Men förutom det uppenbara sambandet mellan suffixautomaten och suffixträdet i samma sträng, kan man också etablera viss överensstämmelse mellan suffixautomaten för en sträng och suffixträdet för en omvänd sträng [20] .
På samma sätt som högerkontexter kan man introducera vänsterkontexter och högerförlängningar som motsvarar de längsta strängarna som har en given vänsterkontext, såväl som en ekvivalensrelation . Om vi överväger rätt tillägg med avseende på strängprefixet språk , då kan vi få det [18] :
Suffixträdet för en sträng kan anges uttryckligen enligt följande:
Här betyder trippeln att strängen från till skrivs på kanten . |
Av vilket det följer att trädet med suffixlänkar för en strängautomat och suffixträdet för en sträng är isomorfa [20] :
Suffixstrukturer för orden abbcbc och cbcbba |
---|
|
På samma sätt som vänster förlängningar kan ett strukturellt lemma [18] också formuleras för höger förlängningar :
Den högra förlängningen av en sträng kan representeras som , där är det längsta ordet så att varje förekomst av in omedelbart följs av ordet . |
I en suffixautomat är längdsträngar inte mer än tillstånd och inte mer än övergångar, och dessa uppskattningar uppnås på strängar respektive [16 ] . Det är också möjligt att formulera ett starkare uttalande om sambandet mellan antalet tillstånd och övergångar i en automat: , där och är antalet övergångar respektive tillstånd [17] .
Maximalt suffix automata |
---|
|
Suffixautomaten för en sträng byggs upp genom att successivt bygga upp ordet som den är byggd för. Inledningsvis finns det en trivial automat byggd för ett tomt ord, och sedan läggs en symbol till det aktuella ordet vid varje steg, vilket innebär en omarrangering av tillstånd och övergångar för automaten [21] .
Efter att ha tilldelat ett nytt tecken till ett ord kommer vissa ekvivalensklasser att ändras. Låt vara det rätta sammanhanget för ordet med avseende på suffixspråket för ordet . Sedan beskrivs övergången från till när man tilldelar en symbol till ett ord med följande lemma [17] :
Låt vara några ord över ett alfabet och vara någon symbol för detta alfabet. Sedan mellan de rätta sammanhangen och orden med avseende på språken för ordens suffix respektive följande förhållande äger rum:
|
Det vill säga när ett tecken läggs till i det aktuella ordet kan ordets rätta kontext bara ändras om det är ett ordsuffix . Av detta följer att uppdelningen av alla ord i ekvivalensklasser med avseende på är en förfining av uppdelningen i ekvivalensklasser med avseende på . Med andra ord, om , då . Dessutom, när nästa symbol läggs till i ordet, kommer delning att ske i högst två tillstånd. Först och främst kommer tillståndet som motsvarar den tomma högra kontexten (det vill säga den som tar språket för ord som inte ingår som ett underord) att delas. Från detta tillstånd kommer ett nytt tillstånd att extraheras som innehåller hela ordet , samt alla dess suffix som förekommer i men inte förekom i . Följaktligen kommer den rätta kontexten för dessa ord, som tidigare var tom, nu endast att bestå av det tomma ordet [17] .
Med hänsyn till kopplingen mellan tillstånden för suffixautomaten och suffixträdets hörn, kan vi också spåra det andra tillståndet, som kan delas när nästa symbol läggs till. Eftersom en ord -till- övergång motsvarar en till- till -övergång för en omvänd sträng, motsvarar att tilldela ett tecken till en sträng att lägga till ett nytt (längsta) suffix till strängens suffixträd . I det här fallet visas inte mer än två hörn: en av dem kommer att motsvara hela ordet och den andra kan visas på den plats där grenen från trädet förekommer. Således motsvarar ett nytt tillstånd den rätta kontexten för hela strängen , och den andra (om någon) kan endast motsvara det tillståndets suffixreferens. Dessa observationer kan generaliseras med satsen [17] :
Låt och . Låt också vara det längsta suffixet som förekommer i , och låt vara dess vänstra förlängning med avseende på , Det vill säga det längsta underordet i ordet sådan att . Då gäller följande för alla underord till ordet :
|
I synnerhet om (till exempel när det inte inträffar alls i och ), uppdelning av det andra tillståndet inte inträffar [17] .
Förutom suffixlänkar måste även sluttillstånden definieras i den nya automaten. Det följer av automatens strukturella egenskaper att suffixen för ett ord är placerade på ett sådant sätt att om , då suffixen vars längd överstiger , ligger i , suffix vars längd är större än , men inte större än , ligger i , och så vidare. Med andra ord, för alla suffix finns det en vertex i suffixets tillståndsväg , som ges av sekvensen . Följaktligen, om vi anger det tillstånd som för närvarande accepterar hela strängen som , så kommer terminaltillstånden (accepterar suffix ) att vara de och endast de tillstånd som ingår i suffixsökvägen [21] .
Eventuella ändringar när du lägger till nästa tecken påverkar inte mer än två nya tillstånd, så ändringar i automatens övergångar kommer också att påverka endast dessa tillstånd. Efter tillskrivning till ordet bildas ett nytt tillstånd , och eventuellt även ett tillstånd . Suffixlänken från kommer att leda till , och från - till . Ord från förekommer endast i som suffix, så det bör inte finnas några övergångar från, och övergångar som leder till det måste leda med tecken från suffix med en längd på minst . Tillståndet är delat från , så övergångar från detta tillstånd kommer att duplicera de för . Och övergångar som leder till det kommer att leda med symbol från stater som motsvarar suffix av längd mindre än och inte mindre än , eftersom tidigare dessa övergångar ledde till och motsvarade den separerade delen av staten. De tillstånd som accepterar dessa ord kan identifieras av tillståndssuffixets sökväg [21] .
Bygga en suffixautomat för ordet abcbc | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
| ||||||||
|
| ||||||||
|
|
De teoretiska resultaten ovan leder till följande algoritm, som tar en symbol och ordnar om ett ordsuffixautomat till en ordsuffixautomat [21] :
Proceduren som implementerar denna algoritm kan beskrivas med följande pseudokod:
funktion add_letter(x) : definiera p = senast tilldela sist = new_state() tilldela len(senast) = len(p) + 1 tills δ(p, x) är definierad: tilldela δ(p, x) = sist, p = länk(p) definiera q = δ(p, x) om q = sista : tilldela länk(sista) = q 0 annars om len(q) = len(p) + 1 : tilldela länk(sista) = q annat : definiera cl = new_state() tilldela len(cl) = len(p) + 1 tilldela δ(cl) = δ(q), länk(cl) = länk(q) tilldela länk(senaste) = länk(q) = cl medan δ(p, x) = q : tilldela δ(p, x) = cl, p = länk(p)Här är det initiala tillståndet för automaten, och är en funktion som lägger till ett nytt tillstånd till automaten. Det antas att , , och lagras som globala variabler.
Beroende på de strukturer som används kan en deterministisk version av algoritmen som beskrivs ovan implementeras i minnestid eller i minnestid , förutsatt att minnesallokering sker i . Samtidigt, för att få en sådan uppskattning av körtiden, är det nödvändigt att utföra en amorteringsanalys av algoritmens inre cykler. Om vi överväger hur parametern ändras efter den första iterationen av den första slingan, kan vi se att den strikt minskar med varje iteration av slingan. Dessutom, om vid den sista iterationen av föregående steg detta värde var lika med , då vid den andra iterationen i nästa steg kommer detta värde att vara lika med . Att den inte överskrider vid något ögonblick av tid, och att mellan cyklerna denna kvantitet ökar med endast en, ger det erforderliga påståendet. En liknande analys kan visa linjäriteten för den totala exekveringstiden för den andra cykeln av algoritmen [21] .
Suffixautomaten är nära relaterad till andra suffixstrukturer och delsträngsindex . Med en suffixautomat av någon sträng är det möjligt att konstruera ett suffixträd av denna sträng i linjär tid genom komprimering och rekursiv traversering av denna automat [22] . Liknande transformationer i båda riktningarna är möjliga mellan en strängsuffixautomat och ett omvänt strängsuffixträd [20] . Dessutom har ett antal algoritmmodifieringar utvecklats som gör det möjligt att bygga en automat för en uppsättning strängar som ges av ett prefixträd [9] , applicera komprimering på det [6] , bibehålla dess struktur i ett glidande fönsterläge [23] , och även bygga om när du lägger till tecken både från slutet och från början av strängen [24] .
Som nämnts ovan kan en komprimerad suffixautomat erhållas från en vanlig suffixautomat genom komprimering (ta bort tillstånd som inte är slutgiltiga och från vilka exakt en övergång leder), samt genom att minimera suffixträdet, om vi antar att alfabetet är bildas av ord skrivna på kanterna trädet. Dessutom kan tillstånden för en komprimerad automat beskrivas explicit, på samma sätt som hur det gjordes för en okomprimerad automat. En tvåvägsordförlängning är det längsta ordet , så att varje förekomst i föregås av ett ord och omedelbart följt av ett ord . När det gäller vänster och höger förlängning betyder detta att tvåvägsförlängningen är vänster förlängning av höger förlängning eller, motsvarande, höger förlängning av vänster förlängning: . När det gäller bilaterala förlängningar kan en automat med komprimerat suffix beskrivas enligt följande [18] :
Den komprimerade suffixautomaten för ett ord kan ges av paret , där:
|
Tvåvägsförlängningar genererar en ekvivalensrelation som beskriver orden som accepteras av samma tillstånd hos den komprimerade automaten. Denna relation är en transitiv stängning av relationen , vilket understryker det faktum att tillstånd för en komprimerad suffixautomat kan erhållas både genom att limma suffixträdets hörn som är likvärdiga vad gäller (suffixträdminimering) och genom att limma tillstånd för en suffixautomat som är likvärdiga när det gäller (komprimerande suffix automat) [25] . Om orden och har samma högra förlängningar, och orden och har de vänstra förlängningarna, då sammanlagt orden , och har samma bilaterala förlängning. I det här fallet kan det visa sig att orden och inte har samma vänster- eller högertillägg. I fallet med , och vänster och höger tillägg är: , men och . I fallet med envägskontexter och tillägg bildade ord från samma ekvivalensklass en kontinuerlig kedja av kapslade prefix eller suffix och kunde unikt bestämmas av längden på de kortaste och längsta orden i klassen. Vid tvåvägsutvidgningar kan man bara säga säkert att ord från samma klass är underord till det längsta ordet från denna klass, och annars kan klasserna ha en ganska komplex struktur. Det totala antalet sådana ekvivalensklasser överstiger inte , vilket innebär att en komprimerad suffixautomat med en längdsträng som mest kommer att ha tillstånd. Antalet övergångar i en sådan automat överstiger inte [18] .
Låt en uppsättning ord ges . På samma sätt som en automat byggd på ett enda ord kan vi överväga en generaliserad suffixautomat som accepterar språket för ord som är suffixet till minst ett ord från . I det här fallet, för antalet tillstånd och övergångar för denna automat, kommer alla samma begränsningar som angavs ovan att vara uppfyllda om vi sätter [25] . Själva konstruktionsalgoritmen liknar i huvudsak algoritmen för att konstruera en automat för en rad, men istället för en pekare till det tillstånd som motsvarar ordet , kommer add_letter- funktionen att ta en pekare till det tillstånd som accepterar ordet . ord , vilket antyder att övergången sker från den nuvarande uppsättningen ord till uppsättningen . Utöver huvudåtgärderna som redan ingår i algoritmen kommer det att vara nödvändigt att separat analysera fallet när strängen redan finns i maskinen - i det här fallet kan du behöva dela upp det tillstånd som accepterar det, liknande hur det gick till när man bildade en suffixlänk i algoritmen för ett enda ord [26] [27] .
En vidareutveckling av denna idé var konstruktionen av en suffixautomat för fallet när uppsättningen inte anges i en explicit form, utan som ett prefixträd på hörnen. Mohry och andra har visat att en sådan automat innehåller på de flesta tillstånd och kan byggas i tid linjär i sin storlek. Samtidigt kan antalet övergångar i en sådan automat nå - till exempel, om vi betraktar en uppsättning ord över alfabetet , kommer den totala längden av ord från denna uppsättning att vara i storleksordningen , antalet hörn i motsvarande prefixträd kommer att vara lika med , och i suffixautomaten kommer det att finnas en ordning av tillstånd och övergångar. Själva algoritmen, föreslagen av Mohri, upprepar till stor del den allmänna algoritmen för att konstruera en automat från en uppsättning strängar, men istället för att varje gång lägga till tecknen i ett ord från uppsättningen från början till slut, korsar algoritmen prefixträdet i genomgångsordningen i bredd och tilldelar nästa tecken i den ordningen , i vilken den möter dem under genomgången, vilket garanterar en amorterad linjär körtid för algoritmen [28] .
I vissa komprimeringsalgoritmer som LZ77 och RLE kan det vara användbart att lagra en suffixautomat eller liknande struktur inte för hela det lästa ordet, utan bara för de sista tecknen. Först och främst uppstår ett sådant behov på grund av detaljerna i datakomprimeringsuppgifter, där de komprimerade strängarna vanligtvis är ganska stora och minnesanvändning är oönskad. År 1985 utvecklade Janet Bloomer en algoritm som stöder en suffixautomat på ett fönster med glidande storlek och körs i värsta fall och genomsnitt, förutsatt att tecknen i ordet som ska komprimeras är oberoende och enhetligt fördelade . I samma arbete visades det att uppskattningen är oförbättrbar - om vi anser att ord erhållna genom formensammanlänkning av flera ord av för en suffixautomat är omöjligt [29] .
Det verkar som om detsamma borde vara sant för suffixträdet , eftersom suffixträdets hörn motsvarar tillstånden för suffixautomaten för den utvikta strängen. Men om en separat vertex för varje suffix inte tilldelas i suffixträdet, kommer det inte att finnas några sådana skarpa hopp och det är möjligt att bygga en amorterad algoritm som stöder suffixträdet på ett glidfönster. En motsvarande algoritm för ett suffixträd, baserad på McCraiths algoritm och stöder att lägga till ett nytt tecken till höger och ta bort ett tecken till vänster, föreslogs 1989 av Edward Fiala och Daniel Green [30] och förklarades 1996 i termer av Ukkonens algoritm av Jesper Larsson [31] [32] . I detta avseende förblev frågan om det är möjligt att upprätthålla ett snabbt glidande fönster för en komprimerad automat, som kombinerar vissa egenskaper hos både en vanlig suffixautomat och ett suffixträd, öppen under lång tid. Ett negativt svar på denna fråga erhölls 2008 av Martin Senft och Tomasz Dvorak, som visade att om alfabetet består av två eller flera tecken, så är den amorterade tiden som krävs för att flytta fönstret med ett tecken i värsta fall av storleken av [33] .
Samtidigt, om den exakta bredden på fönstret inte är viktig och målet endast är att behålla ett fönster vars bredd inte överstiger , i storleksordning, kan detta göras med den ungefärliga algoritm som föreslås av Inenaga et al. 2004. En egenskap hos algoritmen är att "fönstret" som rör sig längs ordet har en variabel längd, som vid något tillfälle varken är mindre eller mer än , medan den totala körtiden förblir linjär [34] .
Strängsuffixautomaten kan användas för att lösa problem som [35] [36] :
Här är det värt att tänka på att någon sträng matas in när automaten redan är byggd och klar att användas.
Suffixautomater har också hittat sin väg in i applikationer som datakomprimering [37] , musikidentifiering från inspelade fragment [38] [39] och genomisk sekvensmatchning [40] .
Strängar | |
---|---|
Stränglikhetsmått | |
Sök efter delsträng | |
palindromer | |
Sekvensjustering | |
Suffixstrukturer | |
Övrig |
Formella språk och formella grammatiker | |
---|---|
Allmänna begrepp | |
Typ 0 | |
Typ 1 |
|
Typ 2 | |
Typ 3 |
|
analysera |