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 .
|
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.
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( ) .
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 forHuomaa, 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 ,..., );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 optimointiUkkosen 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.
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.
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).
Anna tekstin antaa ja syötteeseen tulee joukko kuvioita. Kun tekstistä on rakennettu Ukkosen-algoritmilla suffiksipuu, jokaista kuviota voi hakea seuraavasti:
|
Suffiksipuu voidaan rakentaa merkkijonojoukolle merkkijonojen ketjutuksella tai ilman.
|
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.
Tässä algoritmissa ei ole synteettisiä jälkiliitteitä.
|
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.
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.
Puu (tietorakenne) | |
---|---|
Binääripuut | |
Itsetasapainottavat binaaripuut |
|
B-puut | |
etuliite puita |
|
Avaruuden binaarinen osiointi | |
Ei-binääripuut |
|
Avaruuden hajottaminen |
|
Muut puut |
|
Algoritmit |
jouset | |
---|---|
Merkkijonojen samankaltaisuusmitat | |
Alimerkkijonohaku | |
palindromit | |
Jakson tasaus | |
Suffiksirakenteet | |
muu |