Suffiksi puu

Suffiksipuu  on puu , joka sisältää kaikki jonkin merkkijonon loppuliitteet (ja vain ne). Voit selvittää, sisältyykö merkkijono w alkuperäiseen merkkijonoon t O (|w|) -ajassa , missä |w|  on merkkijonon pituus w .

Perusmääritelmät ja rakenteen kuvaus

  •  on ei-tyhjä äärellinen symbolien joukko , jota kutsutaan aakkosiksi. Aakkosten merkkijono (mahdollisesti tyhjä) on merkitty kirjaimilla r , s ja t . on käänteinen merkkijono. Yksittäiset merkit on merkitty kirjaimilla x, y tai z.  - tyhjä rivi.
  • Aakkosten symbolit ovat kirjaimet a, b, … . Vaikka aakkosten koko otetaan vakiona. |t| tarkoittaa merkkijonon pituutta t .  ovat kaikki merkkijonoja, joiden pituus on m, ja .
  • Merkkijonon t etuliite w  on merkkijono, jossa wv = t jollekin (mahdollisesti tyhjälle) merkkijonolle v . Etuliitettä kutsutaan oikeaksi , jos |v| 0.
  • Merkkijonon t w - liite  on merkkijono, jossa vw = t jollekin (mahdollisesti tyhjälle) merkkijonolle v . Suffiksia kutsutaan oikeaksi, jos |v| 0. Esimerkiksi merkkijonolle "alimerkkijono" alimerkkijono "sub" on sen oma etuliite, "rengas" on sen oma pääte.
  • Merkkijonon t osamerkkijonoa w kutsutaan oikeaksi haaraksi , jos t voidaan esittää kuten joidenkin merkkijonojen kohdalla ja samoin kuin kirjaimet x y . Vasen haara määritellään samalla tavalla. Esimerkiksi "eabceeabcd" alimerkkijono "abc" on oikea haara, koska sen molemmissa esiintymisissä t :ssä on eri merkkejä sen oikealla puolella, mutta sama osamerkkijono ei ole vasen haara, koska sama merkki " e".
  • - puu T  on juurtunut puu , jonka reunat on merkitty sekvenssillä . Jokaisella aakkosten merkillä a on puun T jokaisella solmulla enintään yksi reuna, jonka nimi alkaa merkillä a . Reuna t :stä ​​s :hen , jonka tunniste on v , merkitään .
  • Olkoon k -puun T  solmu , jolloin polku(k) on merkkijono, joka on kaikkien reunatunnisteiden ketjutus juuresta k :hen . Kutsumme sijaintia w , jolle polku( ) = w .
  • Koska jokainen haara on ainutlaatuinen, jos polku( t ) = w , voimme nimetä solmun t nimellä . Solmun alipuu on merkitty . -puussa T esitetyt sanat annetaan joukolla, joka on merkitty sanoilla( T ). Sana w sisältyy joukkosanoihin ( T ) jos ja vain jos on olemassa merkkijono v (mahdollisesti tyhjä), joka  on puun T solmu .
  • Jos merkkijono w sisältyy sanoihin( T ), w = uv ,  on puun T solmu , paria kutsutaan linkkipariksi w suhteessa puuhun T . Jos u  on pisin etuliite, joka  on linkkipari, kutsumme sitä kanoniseksi linkkipariksi . Sitten kirjoitetaan . Sijainnin sanotaan olevan eksplisiittinen, jos |v| = 0 ja implisiittisesti muuten.
  • -puuta T , jossa jokainen reuna on merkitty yhdellä symbolilla, kutsutaan atomiksi (sillä jokainen sijainti on eksplisiittinen). -puuta T , jossa jokainen solmu on joko juuri tai lehti tai haarasolmu, kutsutaan kompaktiksi .
  • Atomipuuta kutsutaan myös (palkiksi). Atomi ja kompakti -puu määritellään yksilöllisesti niiden sisältämien sanojen perusteella.
  • Merkkijonon t päätepuu  on -puu, jossa sanat( T ) = { w | w  on sanan t } osasana. Merkkijonolle t atomiliitepuu merkitään ast( t ), kompakti suffiksipuu on merkitty cst( t ).
  • Merkkijonon t käänteinen etuliitepuu on merkkijonon  jälkiliitepuu .
  • Sisäkkäinen jälkiliite  on jälkiliite, joka sisältyy merkkijonoon t jossain muualla. Pisintä sisäkkäistä päätettä kutsutaan merkkijonon t aktiiviseksi päätteeksi .

Suffiksipuiden ominaisuudet

Lemma. W : n sijainti on eksplisiittinen kompaktissa suffiksipuussa, jos ja vain jos w on t : n ei-sisäkkäinen pääte tai w  on oikea haara.

Todiste. . Jos se on eksplisiittinen, se voi olla joko lehti tai haarapiste tai juuri (tässä tapauksessa w on  myös t :n sisäkkäinen pääte ).

Jos  on lehti, niin se on myös jälkiliite t . Se ei siis saa olla sisäkkäinen pääte, koska muuten se esiintyisi jossain muualla merkkijonossa t : v  on t:n pääte siten , että w on v :  n etuliite . Tämä solmu ei voi olla lehti.

Jos  on haarasolmu, lähtevää reunaa on oltava vähintään kaksi eri tunnisteilla. Tämä tarkoittaa, että on olemassa kaksi erilaista päätettä u , v , että w  on u :n etuliite ja w  on v:n etuliite , missä v = wxs , u = , x . Siksi w  on oikea haara.

. Jos w on t :n sisäkkäinen pääte , sen on oltava lehti. Jos w  on oikea haara, on kaksi päätettä u ja v , u = wxs , v = , x , silloin w on haarasolmu. Lemma on todistettu .

Nyt on helppo ymmärtää, miksi vastaus kysymykseen, onko sana w merkkijonossa t , löytyy O(|w|) -ajassa : tarvitsee vain tarkistaa, onko w sijainti (eksplisiittinen vai implisiittinen) kielessä cst( t ).

Reunatunnisteiden tulee olla osoittimia merkkijonon paikkaan, jotta suffiksipuu kuluttaa O(n) muistia . Reunanimike (p, q) tarkoittaa alimerkkijonoa tai tyhjää merkkijonoa, jos p > q.

Ukkonen ottaa käyttöön nimen avoimet reunat lehtiin päättyville reunoille. Avoimen reunan otsikot kirjoitetaan muodossa (p, ) eikä (p, |t|) , missä  on pituus, aina suurempi kuin |t| .

Olkoon T  -puu . Olkoon  solmu T , v  on pisin pääte w , joka  on myös solmu T . Merkitsemätöntä reunaa välillä - kutsutaan suffiksilinkiksi . Jos v = w , sitä kutsutaan atomiksi .

lausunto. Kohdissa ast( t ) ja cst( t$ ), missä $ t , kaikki suffiksilinkit ovat atomisia.

Todiste. $ -symbolia kutsutaan vartijasymboliksi . Ensimmäinen osa (ast( t )) seuraa määritelmästä, koska sijainnit ovat eksplisiittisiä. Todistaaksemme toisen osan (tapaus cst( t )) on osoitettava, että jokaiselle solmulle on myös solmu cst( t ). Jos  on solmu cst( t ), se on joko lehti tai haarasolmu. Jos on lehti, aw  ei ole t :n sisäkkäinen jälkiliite . Vartiosymbolin ansiosta lemmasta seuraa, että kaikki jälkiliitteet (myös juuri, tyhjä pääte) ovat eksplisiittisiä, koska vain juuri on upotettu jälkiliite. Siksi w on lehti tai juuri. Jos  on haarasolmu, niin aw  on oikea haara, kuten w . Siksi sijainti on eksplisiittinen lemmalla. Väite on todistettu.

Kuten tästä todistuksesta seuraa, vartiosymboli takaa lehtien olemassaolon kaikille päätteille. Tällaisella merkillä ei voi olla muita sisäkkäisiä jälkiliitteitä kuin tyhjiä. Jos jätämme pois vartijamerkin, jotkin jälkiliitteet saattavat sisäkkäin ja niiden sijainnit tulevat epäsuoraksi.

Suffiksipuun muistivaatimukset

lausunto. Kompakti suffiksipuu voidaan esittää muodossa, joka vaatii O(n) muistia.

Todiste. Suffiksipuussa on korkeintaan yksi lehti päätettä kohden (täsmälleen yksi, jossa on huoltajamerkki). Jokaisen sisäisen solmun on oltava haarasolmu, joten sisäisellä solmulla on vähintään kaksi lasta. Jokainen haara lisää lehtien määrää vähintään yhdellä, joten meillä on enintään n sisäistä solmua ja enintään n lehtiä.

Käytämme lähdemerkkijonon indeksointia edellä kuvatulla tavalla edustaaksemme merkkijonoja, jotka ovat reunatunnisteita. Jokaisella solmulla on enintään yksi vanhempi, joten reunojen kokonaismäärä ei ylitä 2n .

Vastaavasti jokaisessa solmussa on enintään yksi suffiksilinkki, jolloin myös suffiksilinkkien kokonaismäärä on rajoitettu 2n :ään . Väite on todistettu.

Esimerkkinä suffiksipuusta, jossa on 2n-1 solmua, harkitse sanan puuta . Merkkijonon t atomiliitepuun koko on O( ) .

Puun rakentaminen lineaarisessa ajassa. mcc- algoritmi . (McCreight's Algorithm)

Mcc - algoritmi alkaa tyhjästä puusta ja lisää jälkiliitteitä pisimmästä alkaen. Mcc - algoritmi ei ole online-algoritmi, eli sen toimintaan tarvitaan koko rivi. Oikea toiminta edellyttää, että merkkijono päätetään muista erillään olevalla erikoismerkillä, jotta mikään pääte ei ole toisen päätteen etuliite. Jokainen puun pääte vastaa lehteä. Algoritmille määritetään  - nykyinen pääte (vaiheessa ), ( head ) - päätteen suurin etuliite , joka on myös toisen päätteen etuliite , jossa . ( häntä ) määritellään .

Mcc-algoritmin avainidea on suhde ja .

Lemma. Jos missä  on aakkosten kirjain,  on merkkijono (voi olla tyhjä), niin  on etuliite .

Todiste. Anna . Sitten on olemassa , sellainen, joka on sekä etuliite että etuliite . Sitten  on etuliite ja on siksi pään etuliite . Lemma on todistettu.

Tiedämme sijainnin , ja jos meillä on jälkiliitteen linkki, voimme nopeasti hypätä pääetuliitteen sijaintiin  ilman , että meidän tarvitsee löytää polkua puun juuresta. Mutta sijainti ei ehkä ole eksplisiittinen (jos sijainti ei ollut eksplisiittinen edellisessä vaiheessa) ja päätelinkkiä ei ehkä ole vielä asetettu solmulle . McCrayn ratkaisu löytää solmun kahdessa vaiheessa: "uudelleenskannaus" ja "skannaus". Kuljemme puuta ylös solmusta, kunnes löydämme päätelinkin, seuraamme sitä ja skannaamme sitten polun uudelleen sijaintiin (mikä on yksinkertaista, koska tiedämme pituuden ja sijainnin olemassa, joten meidän ei tarvitse lukea koko reunaa tarrat liikkuvat alas puussa, voimme vain tarkistaa vain alkukirjaimet ja sanojen pituuden).

Kuva osoittaa tämän ajatuksen. Sen sijaan , että algoritmi yrittäisi löytää polun juuresta solmuun , se hyppää kohtaan , seuraa päätettä kohtaan , skannaa uudelleen polun (mahdollisesti implisiittiseen) sijaintiin ja jää löytääkseen polun osoitteeseen , kiertäen merkki merkiltä.

Algoritmi koostuu kolmesta osasta.

1. Ensin se määrittää edellisen pään rakenteen, etsii seuraavan käytettävissä olevan suffiksilinkin ja seuraa sitä.

2. Sen jälkeen se skannaa uudelleen sen osan edellisestä päästä, jonka pituus on tiedossa (tämä osa on nimeltään ).

3. Lopuksi algoritmi asettaa loppuliitteen linkin , skannaa loput (nimeltään ) ja lisää uuden lehden kohteelle .

Haarasolmu luodaan uudelleenskannauksen toisessa vaiheessa, jos sijaintia ei ole olemassa . Tässä tapauksessa skannaus ei ole tarpeen, koska jos se olisi pidempi kuin , niin se olisi oikea haara, mutta lemman mukaan se on myös oikea haara, joten solmun täytyy olla jo olemassa. Solmu luodaan kolmannessa vaiheessa, jos sijainti ei ole jo selvä.

Algoritmi 1 (mcc, McCreight) Syöte: merkkijono t 1: T : = tyhjä puu; 2: pää 0  := ; 3: n := pituus(t) ; 4: i : = 1 - n tee 5: etsi , , sellainen, että a. pää i-1 = , b. jos solmun pään i-1 esi-isä ei ole juuri ( root ), merkitse se , muuten c. ja ( | pää i-1 |=0) 6: jos ( >0) niin 7: seuraa päätelinkkiä solmusta ; 8: loppu jos 9:  := Tarkista uudelleen( ) ; 10: aseta liitelinkki arvoon 11: ( , tail i ) := Tarkista ( , suf i - );12: lisää häntää i vastaava lehti ; 13: loppu for

Huomaa, että jos silloin ja tunnistetaan yhtä nopeasti kuin algoritmin rivin 7 mukaisen jälkiliitteen linkin jälkeen.

Uudelleenskannaus etsii paikan . Jos sijainti ei ole vielä selvä, uusi solmu lisätään. Tämä tapaus tapahtuu, kun päätä ( ) tarkastellaan kokonaisuudessaan: jos pää on pidempi (ja solmu on jo määritetty), sen on oltava useamman kuin kahden päätteen etuliite ja se on myös :n vasen haara . Sijainti voi olla eksplisiittinen vain, jos kyseinen solmu on jo haarasolmu, ja jos vasenta haaraa ei ollut, sen täytyi olla pidempi, koska havaittiin pidempi etuliite.

Scan - toiminto etsii puun syvyyttä ja palauttaa sijainnin.

Toimenpide 1 Uudelleenskannaus(n, ) Syöte : solmu n , rivi 1: i :=1; 2: kun minä | | tee 3: etsi reuna e=n n' , w 1 = 1 ; 4: jos i +| w |>| |+1 sitten 5: k :=| -i +1 ; 6: jaa reuna e uudella solmulla m ja reunat n m ja m n' ; 7: paluu m ; 8: loppu, jos 9: i := i +| w |; 10: n := n' ; 11: loppu, kun 12: paluu n' ; Toimenpide 2 Scan(n, ) Syöte : solmu n , rivi 1: i :=1; 2: vaikka on reuna e = n n' , w 1 = i do 3: k :=1; 4: kun taas w k = i ja k | w | do 5: k := k +1; 6: i := i +1; 7: loppu, kun taas 8: jos k >| w | sitten 9: n := n' ; 10: else 11: jaa reuna e uudella solmulla m ja reunat n m ja m n' ; 12: paluu ( m , i ,..., ); 13: end if 14: end while 15: return ( n , i ,..., );

Puun rakentaminen lineaarisessa ajassa. ukk- algoritmi . (Ukkosen algoritmi)

Algoritmi, jonka Esko Ukkonen keksi suffiksipuun rakentamiseen lineaarisessa ajassa, on luultavasti yksinkertaisin näistä algoritmeista. Yksinkertaisuus johtuu siitä, että algoritmia voidaan alun perin ajatella yksinkertaisena, mutta tehottomana menetelmänä, joka muutamalla "terveen järjen" toteutuksella saavuttaa parhaiden algoritmien tason suoritusajan suhteen pahimmissakin olosuhteissa. Sama asia tehdään PDF - muodossa kuvien kanssa .

Yksityiskohtainen selitys algoritmista ja toteutuksesta C++  :ssa: cs.mipt.ru (venäjäksi) ja marknelson.us (englanniksi)

Tarvitsemme Ukkosen-algoritmille

1) Implisiittiset suffiksipuut 2) Algoritmin yleinen kuvaus 3) Algoritmin optimointi

Implisiittiset suffiksipuut.

Ukkosen algoritmi rakentaa sekvenssin implisiittisiä suffiksipuita, joista viimeinen muunnetaan todelliseksi merkkijonoliitepuuksi S .

Неявное суффиксное дерево строки S — это дерево, полученное из суффиксного дерева S$ удалением всех вхождений терминального символа $ из меток дуг дерева, удалением после этого дуг без меток и удалением затем вершин, имеющих меньше двух детей. Неявное суффиксное дерево префикса S[l..i] строки S аналогично получается из суффиксного дерева для S[l..i]$ удалением символов $, дуг и вершин, как описано выше.

Minkä tahansa merkkijonon S implisiittisessä suffiksipuussa on vähemmän lehtiä kuin merkkijonon S$ suffiksipuussa, jos ainakin yksi S:n jälkiliitteistä on toisen päätteen etuliite. Terminaali $ lisättiin S:n loppuun vain tämän tilanteen välttämiseksi. Tämä on erittäin tärkeä seikka määritettäessä todellista suffiksipuuta. Jos S kuitenkin päättyy merkkiin, joka ei esiinny missään muualla S:ssä, S:n implisiittisessä suffiksipuussa on lehti jokaiselle päätteelle ja se on siksi todellinen suffiksipuu.

Vaikka implisiittisessä suffiksipuussa ei välttämättä ole lehtiä kaikille päätteille, se koodaa kaikki suffiksit S - jokainen lausutaan jonkin polun merkeillä tämän implisiittisen suffiksipuun juuresta. Jos tämä polku ei kuitenkaan pääty lehtiin, polun loppua osoittavaa merkkiä ei ole. Siten implisiittiset suffiksipuut itsessään ovat hieman vähemmän informatiivisia kuin todelliset. Käytämme niitä vain apuvälineenä Ukkosen algoritmille, jotta saadaan oikea suffiksipuu S:lle.

Algoritmin yleinen kuvaus.

Построить дерево T1 for i from 1 to m - 1 do begin {фаза i + 1} for j from 1 to i + 1 begin {продолжение j} найти в текущем дереве конец пути из корня с меткой S[j..i]. Если нужно, продолжить путь, добавив символ S(i + 1), обеспечив появление строки S[j..i + 1] в дереве, end; end;

Ukkosen algoritmi rakentaa implisiittisen suffiksipuun T i jokaiselle merkkijonon S etuliitteelle S[l..i] alkaen T 1 :stä ja kasvattaen i:tä yhdellä, kunnes rakennetaan T m . S:n todellinen suffiksipuu tulee T m :stä ja koko työ vie O(m) aikaa. Selitämme Ukkosen algoritmin esittämällä ensin menetelmän, jolla kaikki puut rakennetaan O(m³) ajassa ja sitten optimoidaan tämän menetelmän toteutus niin, että ilmoitettu nopeus saavutetaan.

Kolme sääntöä päätteen jatkamiselle.

Muuttaaksemme tämän yleisen kuvauksen algoritmiksi, meidän on määritettävä tarkasti, kuinka päätteen jatkaminen suoritetaan. Olkoon S[j..i] = β S[1..i]:n pääte. Jatkossa j, kun algoritmi löytää pään β nykyisestä puusta, se jatkaa β:ta varmistaakseen, että suffiksi βS(i + 1) on puussa. Algoritmi toimii yhden seuraavista kolmesta säännöstä mukaan.

Sääntö 1. Nykyisessä puussa polku β päättyy lehtiin. Tämä tarkoittaa, että polku β:lla merkitystä juuresta menee jonkin "lehti" kaaren loppuun (lehteen sisältyvä kaari). Kun vaihdat puuta, lisää symboli S(i + 1) tämän lehtikaaren etiketin loppuun.

Sääntö 2. Mikään polku merkkijonon β lopusta ei ala S(i + 1), mutta sieltä alkaa ainakin yksi polku. Tässä tapauksessa on luotava uusi lehtikaari, joka alkaa β:n lopusta ja merkitään symbolilla S(i + 1). Tässä tapauksessa, jos β päättyy kaaren sisään, on luotava uusi kärki. Uuden lehtikaaren lopussa olevalle lehdelle annetaan numero j. Siten säännössä 2 kaksi tapausta on mahdollista.

Sääntö 3. Jokin polku merkkijonon β lopusta alkaa symbolilla S(i + 1). Tässä tapauksessa merkkijono βS(i + 1) on jo nykyisessä puussa, joten mitään ei tarvitse tehdä (implisiittisessä suffiksipuussa loppuliitteen loppua ei tarvitse merkitä eksplisiittisesti).

Hae päätepuusta

Anna tekstin antaa ja syötteeseen tulee joukko kuvioita. Kun tekstistä on rakennettu Ukkosen-algoritmilla suffiksipuu, jokaista kuviota voi hakea seuraavasti:

  1. Saapuvien kuvioiden symbolien mukaan läpikulku suoritetaan rakennetussa suffiksipuussa, kunnes joko kuvion symbolit ovat loppuneet tai seuraava vastaavuus tulee mahdottomaksi.
    1. Anna kuviosymbolien loppua.
      1. Tällöin jokaisen alipuun lehden numerona viimeisimmän osuman pisteestä alkaen on kuvion alkusijainti tekstissä.
      2. Nyt on mahdollista löytää kuvion k aloituskohtaa kulkemalla alipuun poikki täsmäytyspolun lopusta lineaarisessa läpikäymisessä, kuten syvyys- tai leveyshaku, ja huomioimalla havaitut lehtien numerot.
      3. Tämä toimii viivalle asemien lukumäärästä, koska jokaisessa sisäisessä kärjessä on vähintään kaksi lasta ja lehtien lukumäärä polulla on verrannollinen kuljetettujen kaarien määrään.
    2. Toisessa tapauksessa, kun uutta vastaavuutta ei ole, tekstissä ei ole kuviota.
    3. Jos haluat löytää vain yhden esiintymän, sinun on muutettava esikäsittelyä kirjoittamalla jokaiseen kärkeen alipuun pienimmän lehden numero.

Yleistetty suffiksipuu

Suffiksipuu voidaan rakentaa merkkijonojoukolle merkkijonojen ketjutuksella tai ilman.

Merkkijonojen ketjutus

  1. Lisäämme jokaisen rivin loppuun erilaisia ​​vartijamerkkejä (aakkosten ulkopuolisia merkkejä).
  2. Yhdistetään ne kaikki yhdeksi.
  3. Rakennamme tälle riville suffiksipuun.
  4. Tämän puun lehtien numeroissa on numeropareja, joista ensimmäinen vastaa merkkijonoa ja toinen sen aloituspaikkaa.

Tämä lähestymistapa on ongelmallinen synteettisten päätteiden läsnäolon vuoksi, mutta tämä ratkaistaan ​​pienentämällä suffiksiparin toinen indeksi kaarissa lehtien kärkipisteisiin.

Ilman merkkijonojen ketjutusta

Tässä algoritmissa ei ole synteettisiä jälkiliitteitä.

  1. Suffiksipuun rakentaminen merkkijonolle .
  2. Etsimme sarjan ensimmäisiä osumia .
  3. Loppuliitteen puussa täytämme sanan .
  4. Joten seuraaville riveille.

On otettava huomioon, että eri kaareilla tiivistetyt etiketit voivat viitata eri merkkijonoihin, joten kaarille on tallennettava kolme numeroa.

Kahden merkkijonon jälkiliitteet voivat täsmää, mutta samaan aikaan mikään jälkiliite ei ole toisen päätteen etuliite (sentinellin vuoksi). Tämän jälkeen lehti osoittaa kaikkiin tämän päätteen merkkijonoihin ja alkuasentoihin.

Vertailu avainpuihin

Kuviojoukon löytämisen ongelman ratkaisemiseksi on Aho-Korasik-algoritmi. Se etsii kaikki esiintymät:  - kuvioiden kokonaispituus, T - tekstin pituus, k - esiintymien lukumäärä.

Asymptoottisesti kaikkien esiintymien löytäminen suffiksipuusta vie yhtä paljon aikaa. Mutta tosiasia on, että Aho-Korasik käyttää muistia avainpuulle , aikaa rakentamiseen ja aikaa etsimiseen . Mutta suffiksipuu vie muistia , aikaa  - rakentamista ja etsintää.

Eli jos näytteitä on paljon ja enemmän kuin tekstiä, loppuliitepuu on pieni, mutta sen etsiminen kestää kauan. Muuten Aho-Korasik, kun kuviot ovat lyhyitä ja teksti on suurempi, vie vähemmän muistia, mutta suffiksipuuta haetaan nopeammin.

Siten valinta yhden tai toisen välillä riippuu rajaajasta tai muistista.

Katso myös

Kirjallisuus

Linkit