120 likes | 196 Views
KMP (mintaillesztés). Gubicza József (GUJQAAI.ELTE). Az algoritmus.
E N D
KMP (mintaillesztés) Gubicza József (GUJQAAI.ELTE)
Az algoritmus • Hasonlóan működik mint a BruteForcealgoritmus, ám kihasználja a mintában levő prefix-suffix kapcsolatokat (ha vannak), így ha egy szöveg vizsgálata elromlik bizonyos karakternél, nem feltétlen kell a vizsgálatot a minta elejétől újrakezdeni. Csak a megfelelő prefixel kell odébb tolni a mintát, az „elromlott” karakterhez. Példa: B C B C B C D Szöveg: B C B C D Minta: B C B C D
Az algoritmus • Viszont ahhoz, hogy tudjuk a mintával való ugrás lehetséges értékeit, definiálnunk kell egy next függvényt, amely megadja a minta egyes kezdőszeleteire a leghosszabb egymással egyező prefix-szuffix párok hosszát. • Ezt a gyakorlatban egy vektorral lehet megvalósítani, amit az initnext(M[1..m],next[1..m-1]) eljárásban töltünk fel. (M a minta, m hosszúsággal)
Az initnext eljárás Az initnext gyakorlatilag a minta elcsúsztatott keresését hajtja végre önmagán (KMP algoritmussal) , és közben eltárolja a legnagyobb illeszkedő részek hosszát.
Initnext Next[1] = 0 A B B A B C Next[2] = ? Next[2] = 0 M[1] != M[2] A B B A B C Mi a leghosszabb prefix, a mintában a második karakterig tekintve? Mivel a prefix legalább 1 hosszú kell legyen, így az a kérdés, hogy M[1] = M[2] ?
Initnext Next[1] = 0 A B B A B C Next[2] = 0 M[1] != M[2] Next[3] = ? Next[3] = 0 M[1] != M[3] Mi a leghosszabb prefix az első 3 karakterig tekintve? Mivel M[1] != M[2] => M[1..2] != M[2..3] Így 2 hosszú prefix nincs. Így az maradt a kérdés, hogy van-e egy hosszú prefixünk? Mivel tudjuk, hogy M[1] != M[2], így eltolva az alsó mintát a harmadik karakter alá, láthatjuk, hogy M[1] != M[3]. Így..
Initnext Next[1] = 0 A B B A B C Next[2] = 0 M[1] != M[2] A B B A B C Next[3] = 0 M[1] != M[3] Next[4] = ? Next[4] = 1 M[1] = M[4] Mi a leghosszabb prefix az első 4 karakterig? [Felhasználva a táblázatban levő egyenlőtlenségeket.] (3 hosszú prefix?) M[1]!=M[2] => M[1..3] != M[2..4] (2 hosszú prefix?) M[1]!=M[3] => M[1..2] != M[3..4] 1 hosszú prefix vizsgálatánál, már M[1]-et nem kell M[2] és M[3]-al összehasonlítani Így…
Initnext Next[1] = 0 A B B A B C Next[2] = 0 M[1] != M[2] A B B A B C Next[3] = 0 M[1] != M[3] Next[4] = 1 M[1] = M[4] Mi a leghosszabb prefix az első 5 karakterig? [Felhasználva a táblázatban levő egyenlőtlenségeket.] (4 hosszú prefix?) M[1]!=M[2] => M[1..4] != M[2..5] (3 hosszú prefix?) M[1]!=M[3] => M[1..3] != M[3..5] 2 hosszú prefix? Next[5] = ? Next[5] = 2
Folytatás • Ezzel elkészült a nextvektorunk! • Értékeit felhasználva, mostmár elkezdhetünk az algoritmuson is dolgozni. • S lesz a szöveg (hossza n), M a minta (hossza m), i és j az algoritmusban szereplő indexek, valamint szem előtt tartjuk az előbb kapott next értékeit.
S: D A B B A B A B B A B C (->n = 12) M: A B B A B C (->m = 6) Next[1..3] = 0 Next[4] = 1 Next[5] = 2 0 0 1 0 D A B B A B A B B A B C 2 1 3 2 A B B A B C 4 3 5 4 6 5 A vizsgált értékek: i+1 és j+1 Tehát most megnézzük, hogy S szöveg első karaktere megegyezik e, M minta első karakterével Most pedig azt nézzük, hogy a szöveg második karaktere, megegyezik-e a minta első karakterével (csúsztatunk). 6 2 Ezen a ponton, j := next[5], j értéke így 2 lesz!
S: D A B B A B A B B A B C (->n = 12) M: A B B A B C (->m = 6) Next[1..3] = 0 Next[4] = 1 Next[5] = 2 0 0 1 0 2 1 D A B B A B A B B A B C 3 2 4 3 A B B A B C 5 4 6 5 A B B A B C 6 2 6 0 A B B A B C 7 1 8 2 Ha j = m, legyen k := i – (m-1) = 12 – 5 = 7 u := igaz Tehát találtunk (ezt u jelzi) a mintára illeszkedő szövegrészt, mégpedig a 7. pozíciótól 9 3 10 4 Ezen a ponton, j := next[2], j értéke így 0 lesz! 11 5 12 6