Miskolci Egyetem Informatikai Intézet Általános Informatikai Tanszé k Pance Miklós Adatstruktúrák, algoritmusok előadásvázlat Miskolc, 2004 Technikai közreműködő: Imre Mihály, műszaki informatikus hallgató
Szövegminta keresés Legyen adott egy véges ABC, Integer, N>>M. Ekkor a szöveg Keressük az(oka)t az i értéke(ke)t, melyre esetén teljesül, hogy Ha a minták lehetséges halmaza jól behatárolt (szavak) és a szöveg változásának valószínűsége kicsi, azaz statikus szövegről van szó, akkor a keresés meggyorsítható egy a szöveghez kapcsolt indextáblával. (Az indextábla kulcs- pozíció párokat tartalmaz a kulcsérték szerinti gyors elérést biztosító struktúrában, pl. lista és bináris keresés vagy fa; a kulcs lehet szó vagy azzal ekvivalens numerikus kifejezés. ) 2
Szövegminta keresés Dinamikus szövegeknél az indextáblát gyakran kell frissíteni, s ez növeli a műveleti időt. A változások miatt az indextábla nagy része feleslegessé válhat. Közvetlen keresést kell alkalmazni. Elemi, naiv eljárások: - a szöveg minden karakterére ráillesztjük a mintát és a minta betűin végighaladva ellenőrizzük, hogy megegyezik-e a mintabeli és a szövegbeli karakter. Ez összesen (N-M)M összehasonlítást igényel: O(N*M) - javítás: csak addig megyünk, amíg eltérést vagy mintavéget nem találunk. Ekkor a keresési idő jelentősen függ a minta alakjától és O(N+M) és O(N*M) a hatékonyság, általában O(L*N) L> 1 3
Szövegminta keresés Ezek a módszerek úgynevezett felejtő eljárások, mivel nem hasznosítják az előző illesztések során szerzett információkat. 4
Szövegminta keresés KMP Az alapelv: ha az illesztésnél a minta j. pozícióján volt először eltérés, akkor a szöveg és a minta előző (j-1) karaktere azonos volt. Ezt felhasználva határozzuk meg mennyit léphetünk előre. 5 Ha ismerjük a minta felépítését, akkor felesleges mindig vissza menni az (i-j+2)-ik szövegkarakterre, hogy azt újból összehasonlítsuk a minta első karakterével. Akkor ugorhatunk nagyobb lépést, ha tudjuk van-e és milyen hosszú ismétlődő rész a minta vizsgált részének elején és végén. a i-j+1 a i-j+2 aiai szöveg b1b1 b2b2 bjbj minta
Szövegminta keresés KMP Tegyük fel, hogy l hosszúságú a leghosszabb ilyen ismétlődő rész a minta 1..(j-1) közötti szakaszán. 6 Ha l=0, akkor a szöveg ezen része átugorható és a szöveg i- edik elemét vizsgálhatjuk a minta 1. elemével. Ha j=1 lenne, akkor ez már megtörtént, ilyenkor a szövegben egyet előre lépve az (i+1)-edik elemet vizsgáljuk a minta első elemével. l x j' l x bjbj 1 - j
Szövegminta keresés KMP Ha l > 0, akkor a minta csak (j-1-l) elemmel tolható el, azaz a j’ = l+1 indexű mintaelemet kell a szöveg i. elemével összehasonlítani. Egy adott j-hez tartozó j’-t next(j) - nek is nevezik. A next(j) függvény értéke, amit tömbként is tárolhatunk, csak a mintától függ. A next[j] meghatározásának egyik naív módszere lehetne, hogy minden lehetséges l-et növekvő értékkel kipróbálunk, amíg elérjük a maximumot. Egy iteratív módszer: Tegyük fel adott k-ra ismerjük next(k) –t. 7
Szövegminta keresés KMP Ha eggyel növeljük k értékét, akkor ha b k = b next[k] akkor egy l+1 hosszú ismétlődő részt kaptunk, azaz next(k+1) = next(k) + l. Ha viszont b k <>b next[k], akkor egy rövidebb ismétlődést kell vizsgálni, amely az l szakasz ismétlődése lehet csak. Ellenőrizzük, hogy b k = b next[next[k]],ha igen akkor megvan az új hossz, azaz next[k+1] = next[ next[k]] + 1. Ha nem akkor iteratívan tovább megyünk a next[next[ [k]].....] kifejezéssel míg sikerül egyezést találni, vagy már csak egyelemű a vizsgált ismétlődő rész, ekkor next[k+1] = 1. 8 b next[k] bkbk b k+1 minta
Szövegminta keresés KMP A Next tömb előállítása: j = 1; Next[j] = 0; k = 0; while (j < M) { if (b[j] = b[k] || k = 0) { j++; k++; Next[j] = k; } else k = Next[k]; } 9
Szövegminta keresés KMP A keresés: i = 1; j = 1; while ( i <= N && j <= M) { if (a[i] = = b[j] || j = = 0) { i++; j++; } else j = next[j]; if ( j > M) {OK} else {nem talált} } 10
Szövegminta keresés KMP Pl. a: BARBA b: ABBA NEM BARBA DE B A R B A j = 1k = 0 Next[1] = 0 j = 2k = 1 Next[2] = 1 k = 0 j = 3k = 1 Next[3] = 1 k = 0 j = 4k = 1 Next[4] = 1 j = 5k = 2 Next[5] = 2 BAKOSBAROKK BARBI BARBA BARBA BARBA 11
Szövegminta keresés QS Quick Search (QS) ABBARAKRA BARBA Shift[A] = 1, B = 2, C = 6,... R= 3. Az adott betű milyen távol található a minta végétől. Ha x (a szöveg éppen vizsgált karaktere) nincs a mintában, akkor utána tolom a mintában, ha benne van, akkor annyira, hogy az x fedésbe kerüljön a mintabeli utolsó előfordulásával. 12
Szövegminta keresés QS A shift kitöltése: For(i = 1; i < 256; i++) Shift[i] = M + 1; For(i = 1; i <= M; i++) Shift[ TM[i] ] = M – i + 1; 13
Szövegminta keresés QS A keresés: k = 1; while(k <= N – M + 1) { j = 1; i = k; while(TT[i] == TM[j] && j <= M) { i++; j++; } if (j > M) {OK} else k += shift[ TT[ k + j ] ] } 14