220 likes | 340 Views
Parallelle Algoritmen. String matching. Beter algoritme patroonanalyse. Bottleneck in eenvoudig algoritme: WITNESS(j) (j = kandidaat in eerste i-blok) berekenen m.b.v. brute force algoritme Kijkt voor elke k in 1..m-i+1 of dat een geldige WITNESS(j) kan zijn -> O(m) operaties
E N D
Parallelle Algoritmen String matching
Beter algoritme patroonanalyse • Bottleneck in eenvoudig algoritme: WITNESS(j) (j = kandidaat in eerste i-blok) berekenen m.b.v. brute force algoritme • Kijkt voor elke k in 1..m-i+1 of dat een geldige WITNESS(j) kan zijn -> O(m) operaties • Proberen werk te verminderen
Beter algoritme patroonanalyse (2) • Input: een patroon P(1:m) met m = 2s • Output: de WITNESS(1:r) array met r = min(p,2s-1) en p de periode van P
Beter algoritme patroonanalyse (3) • for 1 ≤ i ≤ m/2 pardo WITNESS(i) := 0 • for i = 1 to s - 1 do • j := kandidaat in eerste i-blok, bereken WITNESS(j) via brute force met prefix P(1:2i+1). Als WITNESS(j) != 0, ga verder zoals in vorig algoritme voor deze iteratie, anders is p := j-1 de periode van van P(1:2i+1) • zoek grootste a ≥ i + 1 zodat p een periode is van P(1:2a). Als a = log(m), p is de periode van het hele patroon -> klaar • gebruik lemma (zie verder) om alle WITNESS(l) met p ≤ l ≤ 2a-1 te bepalen en gebruik duels voor een aantal eliminaties bij de rest
Beter algoritme patroonanalyse (4) • Lemma Als: • p periode van P(1:2a) maar niet van P(1:2a+1) • waarden WITNESS(t) voor 2 ≤ t ≤ p beschikbaar en WITNESS(t) ≤ r < 2a Dan: Voor elke k met p < k ≤ 2a geldt: • als k ≠ 1 mod p en k ≤ 2a - r, dan geldt WITNESS(k) = WITNESS(k mod p) • als k = 1 mod p, stel dan w = kleinste index waarvoor P(w) ≠ P(p+w), dan geldt WITNESS(k) = p + w - k + 1
Beter algoritme patroonanalyse (5) Complexiteit: • WITNESS array initializeren: • tijd: O(1) • werk: O(m/2) = O(m) • WITNESS waarden berekenen: • WITNESS(kand. eerste i-blok) berekenen: • tijd: O(1) • werk: O(2i)
Beter algoritme patroonanalyse (6) Complexiteit (vervolg) • WITNESS waarden berekenen: • Als P(1:2i+1) niet periodiek, duels uitvoeren: • tijd: O(1) • werk: O(m/2i) • Als P(1:2i+1) wel periodiek met periode p: • kijken tot waar periode zich uitstrekt (stel tot P(1:2a)): • tijd: (a-i) * O(1) = O(a-i) • werk: = O(2a)
Beter algoritme patroonanalyse (7) Complexiteit (vervolg) • WITNESS waarden berekenen: • WITNESS(j) met 2 ≤ j ≤ 2a-1 bepalen (lemma): • tijd: O(1) • werk: 2a-1 * O(1) = O(2a-1) • duels uitvoeren onder overige elementen: • tijd: (a-i) * O(1) = O(a-i) • werk: (2a-i) * O(m/2a) = O(m/2i)
Beter algoritme patroonanalyse (8) Complexiteit (vervolg) Totaal om van iteratie Totaal: naar iteratie a te gaan: • tijd: O(a-i) O(log m) • werk: O(m/2i + 2a) O(m) PRAM model: CRCW PRAM
Suffix bomen • een digitale zoekboom T is een gewortelde boom met m bladen zodat • elke tak is gelabeld met een element van ∑ en is gericht weg van de wortel • geen twee takken hebben hetzelfde label • elk pad van de wortel naar een blad identificeert een Yi
Suffix bomen • een suffix boom TX is een suffix boom geassocieerd met een string X: analoog als zoekboom, maar elke tak is gelabeld met een substring van X i.p.v. een enkel teken -> compacte versie van een zoekboom
Suffix bomen (2) • Algoritme om suffix boom TX voor string X op te stellen (“vaag”): • input: X# := string X met lengte 2q = m en aangevuld met m-1 sentinels/terminators • output: suffix boom TX • Maak boom T0 = boom met wortel en m takken die de prefixen met lengte m beginnend op positie 1, .., m als label hebben
Suffix bomen (3) • for i = q-1 downto 1 do for alle toppen v van de boom Tq-ipardo if (v heeft meerder takken met label met hetzelfde prefix van lengte 2i) then begin splits deze takken in prefix en rest merge prefixen tot 1 tak maak resten kinderen van nieuwe tak end verwijder toppen waaruit maar 1 boog vertrekt Tq-i+1 := resultaat
Suffix bomen (4) • hoe snel kijken of twee prefixen gelijk zijn? • gelijke prefixen met lengte 2i zelfde ID geven (een getal) • def: Descriptor U (met U substring van X) = koppel (i,|U|), wil zeggen dat substring van X beginnend op positie i met lengte |U| gelijk is aan U • alfabet ∑ hernummeren op basis van input string (via sortering en ranking)
Suffix bomen (5) • def: Array ID[1..|X|,0..log(|X|)] • rijnummer: startpositie substring • kolomnummer: log(len(substring)) • waarde op ID[i,j] = unieke identifier (getal) voor substring U beginnend op positie i met lengte 2j
Suffix bomen (6) Opstellen ID array: • input: string X# met |X|= n = 2k en laatste teken X = # (# komt nergens anders voor in X), elke X(i) is getal tussen 1 en n • output: eerder beschreven ID array • gebruikt hulp-array BB[1..n,1..n+1]
Suffix bomen (7) • for 1 ≤ i ≤ n pardo ID[i,0] := X(i) • for q = 1 to log(n) do for 1 ≤ i ≤ n pardo • k1 := ID[i,q-1], k2 := ID[i+2q-1,q-1] • BB[k1,k2] := i • ID[i,q] := BB[k1,k2] Opmerking: wanneer in stap 2.1 de waardei+2q-1 > n, stel dan k := n+1 • tijd: O(log(n)) werk: O(n*log(n))
Suffix bomen (8) • ID[i,j] = k wil zeggen dat substring met descriptor (i,2j) dezelfde is als die met descriptor (k,2j) (door constructie) • structuur suffix boom: elke top v heeft • een array OUTv(1..n) met OUTv(j) = u voor elke top u die verbonden is met v en j het ID van het label (= een substring) horende bij de boog (v,u) • link naar ouder p(v) • descriptor van de substring horend bij link (p(v),v)
Suffix bomen (9) Implementatie algoritme: • kijken welke takken (v,uk) van top v een label met hetzelfde prefix van lengte 2i-1 hebben: • input: OUTv(j) = uk, top uk bevat descriptor van label van boog (v,uk) = (sk,lk) • output: jID dat prefix van uk met lengte 2i-1 uniek aanduidt • stel jID = ID[sk,i-1] Dit moet gebeuren voor alle toppen v, dus: • tijd: O(1) • werk: O(n)
Suffix bomen (10) • maak nieuwe boog die ouder zal zijn van alle bogen met zelfde prefix met lengte 2i-1 • stel OUTv(jID) := uk • if meerdere uk’s eenzelfde jID hebben en elkaar dus zouden overschrijven then maak nieuwe top v’ met p(v’) = v, descriptor (jID,2i-1) stel OUTv’(ID[sk+2i-1,i-1]) = uk stel OUTv(jID) := v’ stel descriptor uk in op (sk+2i-1,lk-2i-1) Moet weer gebeuren voor alle kinderen -> • tijd: O(1) werk: O(n)
Suffix bomen (11) • verwijderen toppen waaruit maar 1 boog vertrekt • if v na de vorige stap slechts 1 kind heeft then set w := p(v) maak nieuwe top v’ met p(v’) = w, descriptor (sv,lv+2i-1) OUTw(ID[sv,i-1]) := v’ Moet gecontroleerd (en mogelijk uitgevoerd) worden voor alle v’s -> • tijd: O(1) werk: O(n)
Suffix bomen (12) • Oorspronkelijk algoritme voert vorige stappen uit in lus die log(n) maal wordt uitgevoerd. Dus: • tijd: log(n) * O(1) = O(log(n)) • werk: log(n) * O(n) = O(n*log(n))