Introduction Naı̈f Rabin-Karp IFT 436 - Algorithmes et structures de données Filtrage de chaı̂nes de caractères Rachid Kadouche Université de Sherbrooke 1er août 2013 1 Introduction Naı̈f Rabin-Karp À quoi ça sert ? Recherche d’occurrences dans un texte. Éditeur de texte Base de données Analyse syntaxique Recherche d’information Séquence ADN ..... 2 Introduction Naı̈f Rabin-Karp Le problème Formellement : Un texte T [1..n] et un motif P[1..m] (m ≤ n). Les éléments de P et T ∈ Σ, un alphabet fini. On cherche P[1..m] = T [s + 1, .., s + m] tel que 0≤s ≤n−m Principe de base : Algorithme : Recherche-Motif(T, P) 1 2 3 3 s → 0; while P 6= T[s+1, .., s+m] do s ++; return s; Introduction Naı̈f Rabin-Karp Notation Σ : un alphabet. Σ∗ : ens. de chaı̂nes de longueur finies et composées des éléments de Σ. |x| : longueur de la chaı̂ne x. w @ x : w est un préfix de x, si x = wy , notez que |w | ≤ |x|. w A x : w est un suffixe de x, si x = yw notez que |w | ≤ |x|. 4 Introduction Naı̈f Rabin-Karp L’algorithme naı̈f 5 Introduction Naı̈f Rabin-Karp L’algorithme naı̈f Algorithme : Recherche-Naı̈ve(T, P) 1 2 3 4 5 6 n ← length[T ]; m ← length[P]; for s ← 0 to n-m do if P[1..m] = T[s+1.. s+m] then print “occurrence trouvée à la position ” s; Introduction Naı̈f Rabin-Karp L’algorithme naı̈f Algorithme : Recherche-Naı̈ve(T, P) 1 2 3 4 5 n ← length[T ]; m ← length[P]; for s ← 0 to n-m do if P[1..m] = T[s+1.. s+m] then print “occurrence trouvée à la position ” s; Le temps d’exécution dans le pire cas est Θ((n − m + 1)m) 7 Introduction Naı̈f Rabin-Karp Rabin-Karp Pré-traitement : Θ(m). Pire cas : Θ((n − m + 1)m). Cas moyen : O(n). Hachage fait à l’aide de notions de la théorie des nombres tel que la congruence. 8 Introduction Naı̈f Rabin-Karp Rabin-Karp Pré-traitement : Θ(m). Pire cas : Θ((n − m + 1)m). Cas moyen : O(n). Hachage fait à l’aide de notions de la théorie des nombres tel que la congruence. Congruence Si n | (a − b) alors a et b sont congruents modulo n ce que l’on écrit a ≡ b (mod n). 9 Introduction Naı̈f Rabin-Karp Rabin-Karp Cas général : chaque caractère est un nombre en base d avec d = |Σ|. Cas particulier : supposons que Σ = {0, 1, 2, · · · , 9} Une chaı̂ne est vue comme un nombre. La chaı̂ne “31415” ⇒ le nombre 31415. p : valeur décimal de P[1..m]. s : un nombre entre 0 et n − m. ts : valeur décimal de T [s + 1..s + m]. ts = p ⇒ T [s + 1..s + m] = P[1..m]. 10 Introduction Naı̈f Rabin-Karp Calcule de p Calcul de p en Θ(m) avec la règle de Horner p = P[m]+10(P[m−1]+10(P[m−2]+· · ·+10(P[2]+10P[1]) · · · )) 11 Introduction Naı̈f Rabin-Karp Calcule de p Calcul de p en Θ(m) avec la règle de Horner p = P[m]+10(P[m−1]+10(P[m−2]+· · ·+10(P[2]+10P[1]) · · · )) t0 peut être calculé de manière similaire pour T [1..m] en Θ(m). 12 Introduction Naı̈f Rabin-Karp Calcule des ts ts+1 = 10(ts − 10m−1 T [s + 1]) + T [s + m + 1] 13 Introduction Naı̈f Rabin-Karp Calcule des ts ts+1 = 10(ts − 10m−1 T [s + 1]) + T [s + m + 1] Exemple Posons s = 0, m = 5 et T = “31415200 ts = 31415 T [s + 1] = 3 et T [s + m + 1] = 2 Alors : ts+1 = 10(31415 − 10000 ∗ 3) + 2 = 14152 14 Introduction Naı̈f Rabin-Karp Calcule des ts ts+1 = 10(ts − 10m−1 T [s + 1]) + T [s + m + 1] Exemple Posons s = 0, m = 5 et T = “31415200 ts = 31415 T [s + 1] = 3 et T [s + m + 1] = 2 Alors : ts+1 = 10(31415 − 10000 ∗ 3) + 2 = 14152 Le calcul de t1 , t2 , · · · tn−m prend Θ(n − m) 15 Introduction Naı̈f Rabin-Karp ts mod q Soit d = |Σ|, et q un entier ts+1 = (d(ts − hT [s + 1]) + T [s + m + 1]) mod q où h = d m−1 (mod q) . 16 Introduction Naı̈f Rabin-Karp Exemple 17 Introduction Naı̈f Rabin-Karp Exemple - suite 18 Introduction Naı̈f Rabin-Karp ts ≡ p ? Si ts ≡ p (mod q) ; ts = p Par contre ts 6≡ p (mod q) ⇒ ts 6= p ts ≡ p (mod q) : heuristique pour déterminer si une chaı̂ne ne correspond pas. Si ts ≡ p (mod q) alors on doit tester P[1..m] = T [s + 1..s + m] Plus q augmente, plus les chances d’avoir un faux positif diminues. 19 Introduction Naı̈f Rabin-Karp Pseudo-code Algorithme : Recherche-Rabin-Karp(T, P, d, q) 1 2 3 4 5 6 7 8 9 10 11 20 n ← length[T ] ; m ← length[P]; h ← d m−1 mod q; p ← 0 t0 ← 0; for i ← 0 to m do p ← (d · p + P[i]) mod q; t0 ← (d · t0 + T [i]) mod q; for s ← 0 to n-m do if p = ts and P[1..m] = T[s+1 .. s+m] then print “occurrence trouvée à la position ” s; if s < n-m then ts+1 = (d(ts − hT [s + 1]) + T [s + m + 1]) mod q