Algorytmy i Struktury Danych wykład B(hex) Algorytmy tekstowe

Podobne prezentacje


Prezentacja na temat: "Algorytmy i Struktury Danych wykład B(hex) Algorytmy tekstowe"— Zapis prezentacji:

1 Algorytmy i Struktury Danych wykład B(hex) Algorytmy tekstowe
Szymon Grabowski Łódź, 2017

2 Algorytmy tekstowe (string matching, stringology)
Mnóstwo problemów typu: znajdź napis (string), albo ogólniej: wzorzec (pattern), w rozważanym tekście. Zastosowania: edytory tekstu, czytniki pdf / ebooków, systemy plików, biologia obliczeniowa (tekst to DNA lub sekwencja białek, lub RNA…), wyszukiwarki webowe, algorytmy kompresji, wyszukiwanie wzorców 2D (w obrazach), music retrieval (np. rozpoznawanie melodii, być może zniekształconej), skanery antywirusowe, ....

3 Podstawowa notacja i terminologia
Tekst T, wzorzec P, alfabet . Znaki T i P są nad alfabetem . n = |T|, m = |P|  = || (rozmiar alfabetu) $ – terminator tekstu; symbol sztuczny, pierwszy wg alfabetu Napis x jest prefiksem napisu z gddy z = xy, dla pewnego napisu y (y może być pusty, ozn. ). Jeśli z = xy i y  , to x jest prefiksem właściowym z. Podobnie, x jest sufiksem z gddy z = yx dla pewnego napisu y. x jest faktorem z, gddy istnieją napisy a, b takie że z = axb.

4 Wyszukiwanie dokładne (exact string matching)
Problem: Znaleźć wszystkie wystąpienia P[1..m] w T[1..n]. Mówimy, że P występuje w T z przesunięciem s, jeśli P[1..m] = T[s+1..s+m] (jaka jest największa możliwa wartość s?). T jest ‘podawany’ on-line, nie ma czasu na jego wstępną obróbkę. Z drugiej strony P jest zwykle dużo krótszy niż T, więc możemy (i powinniśmy!) przetworzyć P. Klasyczny problem rozważany od ok. 40 lat, nadal pojawiają się nowe algorytmy...

5 Zaawansowane problemy wyszukiwania
wyszukiwanie przybliżone (approximate search) (dopuszczalne różnice między P i podciągiem T); szukanie wielu wzorców naraz (multiple search); wyszukiwanie rozszerzone (klasy znaków, wyrażenia regularne, etc.); wyszukiwanie 2D (w obrazach). Bardzo trudne, jeśli chcemy wprowadzić niewrażliwość na obroty i/lub skalowanie, i/lub zmienną jasność…

6 off-line search = indexed search
Wyszukiwanie on-line kontra off-line on-line (Boyer-Moore, KMP, etc.) – cały tekst T musi być przeskanowany (nawet jeśli można przeskoczyć nad niektórymi jego znakami); off-line – bazuje na obróbce wstępnej tekstu, ale za to wyszukiwanie prawdziwie subliniowe w |T|. off-line search = indexed search Dwa typy indeksów tekstowych: indeksy na słowach (word-based indexes), np., Glimpse (Manber & Wu, 1994); indeksy pełnotekstowe (full-text indexes), np., drzewa sufiksowe, tablice sufiksowe.

7 Wyszukiwanie dokładne, przykład

8 Wyszukiwanie dokładne, c.d.
Algorytm naiwny (brute-force) próbuje dopasować P na każdej pozycji T. Tzn. dla każdego i, i=1..n–m+1, P[1..m] jest ‘przykładany’ do T[i..i+m–1]. Dokładniej, porównujemy P[1..m] do T[startpos...startpos+m+1] od lewej do prawej; jeśli mamy niezgodność, to przesuwamy P o 1 znak i kontynuujemy w ten sam sposób. Czas pesymistyczny: O(mn). W praktyce jednak czas jest bliski O(n). Nie jest to zwykle bardzo zły algorytm, ale istnieją algorytmy dużo szybsze.

9 Alg naiwny w działaniu Najgorszy przypadek
Najgorszy przypadek Niech T = aaaaaaaaa...b (np. jedno b poprzedzone literami a). Niech P = aaaaab. Na każdej pozycji T stwierdzamy nietrafienie po dokładnie |P| = 6 porównaniach znaków.

10 Idea algorytmu Knutha-Morrisa-Pratta (KMP) (1977)
Prosta obserwacja: jeśli mamy niezgodność na pozycji j, przy użyciu alg. naiwnego, to wiemy, że poprzednie j–1 znaków było zgodnych. KMP wykorzystuje ten fakt: po niezgodności na pozycji j przesuwa P o (j –1) minus długość najdłuższego prefiksu właściwego P będącego także sufiksem P[1..j–1]. Skomplikowane? Nie bardzo. Oto przykład: P = abababc. T = ababad... Niezgodność na pozycji 6 (b  d). KMP, w czasie O(1) (dzięki wstępnej obróbce wzorca), ustali, że P można bezpiecznie przesunąć o 5 – 3 = 2. Dlaczego 5, dlaczego 3? 5 = |ababa|. 3 = |aba|.

11 Liniowy czas w najgorszym (ale i najlepszym) przypadku.
Właściwości KMP Liniowy czas w najgorszym (ale i najlepszym) przypadku. Dodatkowa pamięć: O(m) (dla tablicy budowanej w fazie wstępnej obróbki). Nie jest praktyczny: ok. 2x wolniejszy niż alg. naiwny (wg: R. Baeza-Yates & G. Navarro, Text Searching: Theory and Practice). Niemniej, w pewnym stopniu zależy to od alfabetu: przy małym alfabecie (np. DNA) KMP działa stosunkowo szybko.

12 Algorytm Boyera-Moore’a (1977). Pierwszy algorytm z przeskokami!
KMP jest optymalny w najg. przypadku, ale nigdy nie przeskakuje znaków w T. Tzn. czas (n) obowiązuje też w najlepszym przypadku. Ale jak można przeskakiwać znaki w T przy szukaniu?! Idea: porównaj P z wycinkiem T od prawej do lewej. Jeśli np. znak T wyrównany z ostatnim znakiem P nie występuje nigdzie w P, to możemy przesunąć P o całą jego długość! Ale jak szybko sprawdzić, czy dany symbol nie występuje w P?

13 Idea Boyera-Moore’a Prosta obserwacja: zwykle m << n i  << n. A zatem dowolna procedura preprocessingu w czasie O(m + ) jest praktycznie darmowa. Wstępna obróbka w alg. BM używa tablicy o rozmiarze  zwracającej informację o ostatnim (tj. położonym najbardziej na prawo) wystąpieniu każego symbolu w P (także informację, jeśli dany symbol wcale nie występuje w P). Dzięki tej tablicy na pytanie „jak daleko możemy przesunąć P po stwierdzeniu niezgodności?”, można odpowiedzieć w czasie O(1).

14 Oryginalny BM nie jest aż tak fajny…
Boyer & Moore próbowali być zbyt sprytni.  Wprowadzili nie jedną, lecz dwie heurystyki, żeby zmaksymalizować przesunięcie wzorca. Wystarczy jednak użyć jednej z nich (tzw. bad-character heuristic). Zastosowanie obu wydłuża (nieco) średnie przesunięcie, ale dodatkowe obliczenia też kosztują…

15 Boyer-Moore-Horspool (1980) Bardzo prosty i praktyczny wariant BM
Źródło: R. Baeza-Yates & G. Navarro, Text Searching: Theory and Practice, Formal Languages and Applications, Physica-Verlag, Heidelberg.

16 Text T: początek wiersza T.S. Eliota The Hippopotamus.
Przykład BMH Z powodów technicznych (stosunkowo duży alfabet), nie przedstawiamy całej tablicy d. Text T: początek wiersza T.S. Eliota The Hippopotamus.

17 Przykład BMH, c.d. Co dalej? Odczytujemy, że d[‘s’] = 12, więc przesuwamy P o jego całą długość (gdyż nie ma innego ‘s’ w P, prawda?). I wyszukiwanie jest kontynuowane...

18 Złożoności czasowe dla przyp. średniego i najgorszego
Założenie dla analizy średniego przypadku: rozkład znaków jednostajnie losowy, znaki w T ‘wylosowane’ niezależnie od siebie. Podobnie dla P. Oczywiście zakładamy m = O(n) i  = O(n), więc zamiast np. O(n+m) piszemy tylko O(n). Alg naiwny: O(n) średnio, O(mn) pesymistycznie. KMP: O(n) średnio i pesymistycznie. BM: O(n / min(m,)) średnio i O(mn) pesymistycznie. BMH: złożoności jak przy BM. 18

19 Złożoności czasowe dla przyp. średniego i najgorszego, c.d.
Ograniczenia dolne na średni i najgorszy przypadek to odpowiednio: (n log(m) / m) i (n). Zauważmy, że n log(m) / m jest w praktyce bliskie n / m (w teorii są one ‘równe’, tj. złożoność się nie zmienia, gdy m = O(1)). Backward DAWG Matching (BDM) (Crochemore et al., 1994) – ten alg osiąga optimum w średnim przypadku. Pewne jego odmiany, np. TurboBDM i TurboRF (Crochemore et al., 1994), osiągają także O(n) w najg. przypadku nie tracąc optymalnej złożoności dla przypadku średniego. 19

20 Wyszukiwanie wielu wzorców (multiple string matching)
Dany jest zbiór wzorców P1 , ..., Pr , a zadanie polega na znalezieniu wszystkich wystąpień dowolnego Pi (i=1..r) w tekście T. Podejście trywialne: uruchom alg. szukania jednego wzorca r razy. O wiele za wolne, nawet jeśli r nie jest duże. (Wybrane) zastosowania: grupowe („batchowe”) zapytania w kolekcji tekstów, szukanie różnych wariantów pisowni słowa / frazy (np. P1 = “color” i P2 = “colour”), programy antywirusowe (szukanie sygnatur wirusów). 20

21 Dostosowanie podejścia Boyera–Moore’a do wyszukiwania wielu wzorców
BMH używa tablicy przeskoków d, aby wykonać najdłuższe bezpieczne przesunięcie wzorca nad tekstem, wykorzystując tylko 1 znak tekstu. Przy r wzorcach też możemy „skakać”. Ale skoki będą zwykle krótsze. Przykład: P1 = bbcac, P2 = abbcc, T = abadbca... 5-ty znak T to b, przesuwamy wszystkie wzorce o 2 znaki (2 = min(2, 3)). Konieczne weryfikacje. 21

22 Drzewo poszukiwań cyfrowych / trie / digital tree (de la Briandais, 1959; Fredkin, 1960)
Etymologia: reTRIEval (wymowa: jak try, żeby się odróżniało od tree) Drzewo trie przechowujące klucze: an, ant, all, allot, alloy, aloe, are, ate, be 22

23 Drzewo trie – dylemat implementacyjny
Istnieje naturalna relacja (kompromis) między czasem wyszukiwania a zużyciem pamięci. Jeśli trzymamy w węźle drzewa trie tylko wskaźniki z „istniejących” w tym węźle symboli, to jest to efektywne pamięciowo, ale czas na węzeł wynosi O(log ) (wysz. binarne w węźle). Uwaga: wyszukiwanie binarne jest dobre w teorii (dla najgorszego przypadku), ale dla względnie małych alfabetów (i ewent. poza górnymi piętrami drzewa trie) jest niezbyt szybkie w praktyce. Czas na węzeł można zredukować do O(1) (pojedynczy „lookup”), jeśli węzeł zużyje O() pamięci. Podsumowując, wyszukiwanie wzorca zajmuje O(m log ) lub O(m) czasu w najgorszym przypadku. 23

24 Patricia trie (skompresowane drzewo trie)
W większości przypadków drzewa trie zużywają dużo pamięci. Często stosowane ulepszenie: kompresja ścieżek, tj., łączenie węzłów nie posiadających rozgałęzień ze swoim (jedynym) dzieckiem = Patricia trie (Morrison, 1968). Inne znane idee: używaj inteligentnie tylko 1 bitu na wskaźnik, albo jednego wskaźnika na wszystkie dzieci węzła. PATRICIA to skrót od Practical Algorithm To Retrieve Information Coded in Alphanumeric 24

25 Patricia trie, przykład

26 Z cytowanego artykułu:
Algorytm Rabina–Karpa połączony z wyszukiwaniem binarnym (Kytöjoki i in., 2003) Z cytowanego artykułu: Preprocessing: hash values for all patterns are calculated and stored in an ordered table. Matching can then be done by calculating the hash value for each m-char string of the text and searching the ordered table for this hash value using binary search. If a matching hash value is found, the corresponding pattern is compared with the text. 26

27 Algorytm Rabina–Karpa połączony z wyszukiwaniem binarnym, c.d.
Kytöojoki i in. zaimplementowali tę metodę dla m = 8, 16 i 32. Wartości haszów przy m = 8: Z 4 pierwszych bajtów wzorca jest tworzony int 32-bitowy. Analogiczny int z ostatnich 4 bajtów. Te wartości są XORowane, dając wynik: Hash(x1 ... x8) = x1x2x3x4 ^ x5x6x7x8 Hasz dla m = 16: Hash16(x1 ... x16) = ( x1x2x3x4 ^ x5x6x7x8 ) ^ ( x9x10x11x12 ^ x13x14x15x16 ) Hash32 analogicznie. 27

28 Automat Aho–Corasick (AC) (1975)
Ten algorytm to uogólnienie KMP. Dla małych (w szczególności stałego rozmiaru) alfabetów jest on budowany w czasie O(M), a zapytania są obsługiwane w czasie O(n + z) (M – suma długości wzorców, z – ich łączna liczba wystąpień w T). Dori & Landau (2005) pokazali, jak obsłużyć alfabety o rozmiarze  = nc, gdzie c > 0 jest stałą (tzw. integer alphabets) przy czasie budowy O(M) i czasie szukania O(n log  + z). Automat AC to w zasadzie trie dla wzorców + krawędzie „fail” (failure links).

29 Trie dla zbioru wzorców: { he, she, his, hers }
AC, przykład [ ] Trie dla zbioru wzorców: { he, she, his, hers } L(v) – etykieta węzła v, np. L(2) = she Automat AC dla tego samego zbioru wzorców; strzałki przerywane to krawędzie fail.

30 AC bardziej formalnie (w oparciu o [ http://www. cs. uku
3 funkcje: funkcja goto: g(q, a) zwraca stan osiągany ze stanu q poprzez przeczytanie znaku a; innymi słowy, jeśli krawędź (q, v) jest etykietowana znakiem a, to g(q, a) = v. g(0, a) = 0 dla każdego znaku a, który nie etykietuje krawędzi wychodzącej z korzenia (automat pozostaje w stanie początkowym). W przeciwnym razie: g(q, a) = .

31 AC bardziej formalnie, c.d.
funkcja fail: f(q) dla q   zwraca stan, który osiągamy przy „mismatchu”. Dokładniej, f(q) jest węzłem etykietowanym przez najdłuższy sufiks właściwy w napisu L(q), taki że w jest prefiksem pewnego wzorca funkcja output: out(q) zwraca zbiór wzorców rozpoznawanych przez stan q. Szukanie wzorców w T[1..n]

32 Alg. Aho–Corasick, analiza złożoności wyszukiwania
Dla każdego znaku z T automat wykonuje zero lub więcej przejść (tranzycji) fail, po których następuje jedno goto. Każde goto albo pozostaje w korzeniu (krok g(0, a) = 0), albo zwiększa głębokość stanu (=jego odległość od korzenia) o 1. Łącznie biorąc głębokość stanu jest zatem zwiększona (o 1) co najwyżej n razy. Każde fail przybliża bieżący stan do korzenia, zatem łączna liczba przejść fail jest także  n. z wystąpień wzorca raportuje się w czasie O(1) na wystąpienie (zwykle wysyłając na wyjście ID(s) pasującego wzorca + pozycję startową jego wystąpienia). Łączny czas: O(z). Łączny czas wyszukiwania: O(n + z) (jeśli automat jest już zbudowany, co można zrobić w czasie O(M)).

33 Wyszukiwanie przybliżone
Wyszukiwanie dokładne (exact string matching) – problem niemal zamknięty w teorii (nowe algorytmy to dużo częściej heurystyki niż nowe osiągnięcia teoretyczne). Wyszukiwanie przybliżone (approximate string matching) za to jest b. aktywnie rozwijanym poletkiem badawczym. Istnieje wiele definicji podobieństwa napisów, np. dla tolerowania literówek w tekście, fałszywych nut i zmian tonacji w sekwencjach muzycznych odmian (mutacji) sekwencji DNA, etc. etc. 33

34 Odległość edycyjna (=odległość Levenshteina)
Jedna z najczęściej używanych miar odległości dla tekstów. edit(A, B) to minimalna liczba elementarnych operacji wymaganych do przekształcenia napisu A w B (lub odwrotnie). Dozwolone elementarne operacje to: wstaw znak (insert), usuń znak (delete), zastąp znak innym (substitute). Przykład: edit(pile, spine) = 2 (wstaw s; zastąp l znakiem n). 34

35 Rekurencja dla odległości edycyjnej
Chcemy obliczyć ed(A, B). Algorytm programowania dynamicznego (dynamic programming, DP) polega na wypełnieniu macierzy C0..|A|, 0..|B| , gdzie Ci,j przechowuje najmniejszą liczbę operacji przekształcających A1..i w B1..j. Ci,0 = i C0,j = j Ci,j = if (Ai = Bj) then Ci–1,j– else 1 + min(Ci–1,j, Ci,j–1, Ci–1,j–1) 35

36 Progr. dyn. dla odległości edycyjnej, przykład
A = surgery, B = survey (Popularny przykład, np. z doktoratu Gonzalo Navarro, 1998, ftp://ftp.dcc.uchile.cl/pub/users/gnavarro/thesis98.ps.gz) 36

37 Lemat o partycjonowaniu dla odl. edycyjnej
Szukamy przybliżonych wystąpień wzorca, z maksymalnym dozwolonym błędem k. Lemat (Rivest, 1976; Wu & Manber, 1992): Jeśli wzorzec podzielimy na k+1 (rozłącznych) części, to przynajmniej jedna z tych części musi pojawić się w postaci dokładnej (bezbłędnej) w przybliżonym wystąpieniu wzorca. Ogólniej: jeśli dzielimy P na k+l części, to przynajmniej l części musi pojawić się w postaci dokładnej. 37

38 Lemat o partycjonowaniu jest szczególnym przypadkiem zasady Dirichleta
Zasada szufladkowa Dirichleta jest bardzo oczywistą (lecz użyteczną w matematyce) obserwacją. Jeśli np. mamy 10 królików i 9 klatek, to (przynajmniej) w 1 klatce muszą być ulokowane (przynajmniej) 2 króliki. Albo też odwrotnie (co bardziej pasuje dla naszego lematu): 9 królików i 10 klatek  co najmniej jedna klatka musi być pusta. Zasada D. formalnie: Dla dowolnej liczby naturalnej n > 0, nie istnieje bijekcja między zbiorem S, takim że |S| = n a jego podzbiorem właściwym. 38

39 Zasada pudełkowa Dirichleta, proste (matematyczne) zastosowania
Wśród mieszkańców Łodzi co najmniej dwie osoby mają tę samą liczbę włosów na głowie. W grupie N osób (N  2) istnieją dwie osoby mające taką samą liczbę znajomych. Czyli: w każdym nieskierowanym grafie skończonym o co najmniej dwu węzłach istnieją dwa węzły o tym samym stopniu. Jeśli w kole o promieniu 9 znajduje się 101 punktów, to istnieje wśród nich para punktów oddalonych od siebie o mniej niż 2.

40 Lemat o partycjonowaniu w praktyce
Wyszukiwanie przybliżone z maksymalnym błędem k (odl. edycyjna): podziel wzorzec P na k+1 rozłącznych części o długości m / (k+1), dla tych k+1 podwzorców uruchom dowolny alg. wyszukiwania dokładnego wielu wzorców, zweryfikuj wszystkie trafienia (potrzebne narzędzie takiej weryfikacji – zwykle algorytm progr. dynamicznego). 40

41 Lemat o partycjonowaniu, przykład
Wzorzec P = telewizor Tekst T = Pod ścianą stoi teleiwzor. k = 2, czyli dopuszczamy najwyżej 2 błędy w sensie Levenshteina. Algorytm: dzielimy wzorzec na 2+1=3 rozłączne (i możliwie równe) części. Tj.: tel ewi zor Szukamy tych podwzorców naraz i tylko wtedy, jeśli któryś z nich występuje dokładnie w tekście, to jest szansa na przybliżone trafienie (trzeba wtedy dokonać weryfikacji).

42 Podobieństwo lokalne Miara globalna: ed(A,B) czy problem wyszukiwania: ed(T[j’...j], P[1..m]) ? Jak zaadaptować alg DP do wyszukiwania (krótkiego) wzorca P w (długim) tekście T? Bardzo prosto. Każda pozycja w T może być początkiem trafienia, więc ustawiamy C0,j = 0 dla wszystkich i. Następnie idziemy kolumnami (obliczamy kolumny C[j], dla kolejnych j=1...n). 42

43 Ale zlożoność nadal wynosi O(mn), w każdym przypadku. 
Podejście DP Bardzo elastyczne: np. można przypisać dodatnie wagi (wartości ‘kary’) osobno dla każdego elementarnego typu błędu (tj. insert, delete, substitute), a wtedy taką uogólnioną edycyjną miarę odległości można policzyć po trywialnej modyfikacji algorytmu podstawowego. Formuła dla tego przypadku (wariant problemu: „search”), na pozycji tekstu j: Ale zlożoność nadal wynosi O(mn), w każdym przypadku.  Opracowano zatem algorytmy niekoniecznie lepsze w przyp. najgorszym, ale dużo szybsze w przypadku średnim. 43

44 Oczywiście indel(A, B)  edit(A, B).
Odległość indel B. podobna do odl. Levenshteina (edycyjnej), ale tylko Insercje i DELecje są dozwolone. Oczywiście indel(A, B)  edit(A, B). Funkcje odległości edit() i indel() są metrykami. Czyli: d(X, Y)  0 d(X, Y) = 0 gddy X = Y d(X, Y) = d(Y, X) d(X, Y)  d(X, Z) + d(Z, Y) 44

45 Odległość Hamminga Bardzo prosta, ale ograniczone zastosowania.
dH(S1, S2) jest liczbą pozycji, na których S1 i S2 się różnią Jeśli | S1 |  | S2 |, to dH(S1, S2) = . Przykład S1 = Donald Duck S2 = Donald Tusk dH(S1, S2) = 2. 45

46 Najdłuższa wspólna podsekwencja (longest common subsequence, LCS)
Dane są napisy A, B, |A| = n, |B| = m, znajdź najdłuższą podsekwencję zawartą w obu. Dokładniej, znajdź 1  i1  i2  ...  ik–1  ik  n, oraz 1  j1  j2  ...  jk–1  jk  m, takie że A[i1] = B[j1], A[i2] = B[j2], ..., A[ik] = B[jk] zaś k jest zmaksymalizowane. k jest długością ciągu LCS(A, B) i bywa też oznaczane przez LLCS(A, B). Czasem jesteśmy zainteresowani prostszym problemem: wyznaczeniem tylko LLCS, a nie pasującej podsekwencji. 46

47 Formuła programowania dynamicznego dla LCS
Zastosowania LCS narzędzie diff (np. do porównywania dwóch wersji danego pliku lub dwóch wersji większego projektu programistycznego) biologia molekularna (Biolog odkrywa nową sekwencję. Do jakiej innej (jakich innych) sekwencji jest ona najbardziej podobna?) znalezienie najdłuższego podciągu rosnącego w permutacji liczb 1..n Formuła programowania dynamicznego dla LCS 47

48 Obliczanie długości LCS algorytmem programowania dynamicznego (DP)
[ 48

49 Indeksowanie tekstu (text indexing)
Jeśli planujemy wiele wyszukiwań w tym samym tekście (np. podręczniku, zbiorze artykułów w archiwum gazety na www), to warto poświęcić pamięć i czas preprocessingu (wstępnej obróbki), aby zbudować indeks obsługujący szybkie wyszukiwania. Indeks pełnotekstowy (full-text index): P może być na dowolnej pozycji w T. Indeks na słowach (word-based index): znajdzie wystąpienia P w T tylko tam, gdzie zaczynają się one na granicy słowa. (Nieraz to wystarcza, a przy tym może być szybsze w praktyce / oszczędniejsze pamięciowo / elastyczne.) 49

50 Drzewo sufiksowe (suffix tree) (Weiner, 1973)
Drzewo sufiksowe ST(T) to zasadniczo struktura Patricia trie zawierająca wszystkie n sufiksów tekstu T. Pamięć: O(n log n) bitów (z dużą stałą). Czas budowy: O(n log ) (w przypadku ogólnym) lub O(n) (Farach, 1997) dla alfabetów „całkowitoliczbowych” (integer alphabets,  = {1, 2, …, },  = nO(1)). Czas wyszukiwania wzorca: O(m log  + occ) (occ – liczba wystąpień wzorca P w T) 50

51 Przykład drzewa sufiksowego
51

52 Drzewo sufiksowe, większy przykład

53 Drzewo sufiksowe, zalety i wady
+ znakomita złożoność czasu wyszukiwania, + dobra szybkość wyszukiwania w praktyce, + możliwość obsługi również wielu zaawansowanych rodzajów zapytań, duże wymogi pamięciowe: ok. 20n bajtów dla najg. przypadku nawet w najlepszych implementacjach (ok. 10n średnio w implementacji Kurtza), algorytmy budowy są dość skomplikowane 53

54 Tablica sufiksowa (suffix array) (Manber & Myers, 1990)
B. prosty, a efektywny indeks pełnotekstowy. Posortujmy wszystkie sufiksy T, trzymając ich indeksy w zwykłej tablicy (n indeksów, każdy typowo na 4 bajtach). Trzymajmy dodatkowo sam tekst T (łączna pamięć: 4n+1n = 5n bajtów, dużo mniej niż przy drzewie sufiksowym). Szukanie P: porównaj P z sufiksem medianowym (tj.: przeczytaj indeks medianowego sufiksu, następnie odczytaj jego prefiks z oryginalnego T). Jeśli napisu P tam nie ma, to idź w lewo lub w prawo, w zależności od wyniku porównania, z każdym krokiem dzieląc na pół pozostały zakres sufiksów. Innymi słowy: zastosuj strategię wyszukiwania binarnego. 54

55 SA, przykład T = abracadabra
W zasadzie moglibyśmy mieć symbol $ (terminator) po T… 55

56 SA, przykład, c.d. Sortujemy leksykograficznie sufiksy
SA(T) = {11, 8, 1, 4, 6, 9, 2, 5, 7, 10, 3} 56

57 Właściwości wyszukiwania w tablicy sufiksowej
Mechanizm szukania: każdy wzorzec występujący w tekście T musi być prefiksem pewnego sufiksu T. Czas w najg. przypadku: O(m log n + occ). Ale w praktyce jest on bliższy O(m + log n + occ). Manbers & Myers (1990) podali trick przyspieszający szukanie z użyciem SA: tablica LUT (lookup table) o rozmiarze k elementów (gdzie k jest małą liczbą nat.), przechowuje zakresy przedziałów dla prefiksów o długości k znaków. Dzięki temu dalsze wyszukiwanie binarne ma już mniej kroków. SA: bardzo prosta i praktyczna struktura indeksująca tekst. 57

58 Odpowiedniość między liśćmi drzewa sufiksowego a elementami tablicy sufiksowej
Źródło: M. Kasahara and S. Morishita, Large-Scale Genome Sequence Processing, 2006.

59 SA-hash (Grabowski & Raniszewski, 2014)
k liczb całkowitych (typowo 4-bajtowych) w idei LUT Manbera i Myersa (S52) wymusza użycie małego k. Możemy jednak użyć tablicy haszującej (HT) dla tylko tych prefiksów, które występują w tekście ( większe k w praktyce). Powyższe teksty o dług. 200 MB (M=10242)

60 i3 2.1 GHz, 8 GB RAM, Ubuntu 14.04.1 LTS, C++, 64-bit gcc 4.8.2
SA-hash, czasy i3 2.1 GHz, 8 GB RAM, Ubuntu LTS, C++, 64-bit gcc 4.8.2

61 SA-hash, poprawa szybkości
Współczynnik zapełnienia HT: 90%, funkcja haszująca: xxhash ( )

62 SA-hash, zużycie pamięci


Pobierz ppt "Algorytmy i Struktury Danych wykład B(hex) Algorytmy tekstowe"

Podobne prezentacje


Reklamy Google