Algorithmie PC 4 : Méthodes de recherche corrigé 1 Fonction

publicité
Algorithmie
PC 4 : Méthodes de recherche
corrigé
1
Fonction d’adressage
Un fonction d’adressage, ou fonction de hashage est une fonction permettant
d’associer un entier de [0,N] à un ensemble de données (des chaı̂nes de caractères,
par exemple).
De façon générale, comme toute donnée en informatique est dénombrable
(i.e. toute donnée est représentée par une suite de 0 et de 1), une fonction
d’adressage est une fonction de l’ensemble des entiers naturels dans un sousensemble fini d’icelui (qui sera la plupart du temps les entiers de [0, N ], avec N
entier).
1.1
Une fonction d’adressage particulière
Une bonne fonction d’adressage doit avoir un caractère “aléatoire” pour que les
données se répartissent bien entre tous les entiers de [0, N ].
Une fonction très utilisée est la fonction modulo. En prenant deux entiers k
et k’, k modulo k’ est égal au reste de la division entière de k par k’.
1.1.1
Implémentez un algorithme permettant de calculer la fonction modulo. Quelle est sa complexité ?
L’algorithme 1 est une possibilité. Il y a k’/k itérations, la complexité est
donc en O(k 0 /k).
1.1.2
On suppose que chaque lettre de l’alphabet est codée de façon binaire
sur 5 bits par sa position dans l’alphabet (00001 pour A, 00101 pour
E, etc.). Si l’on veut des entiers entre 0 et 100 (en notation décimale),
quelle est l’adresse via la fonction modulo de la chaı̂ne de caractère
CLE ?
1
Algorithme 1 Fonction modulo
Données
un entier k
un entier k’
Début
i=1
tant que k*i < k’ faire
i=i+1
i=i-1
rendre k’-k*i
Fin
Comme C=00011, L=01100 et E=00101, le code de CLE est égal à 000110110000101.
Ce nombre est égal à 211 +210 +28 +27 +22 +20 = 2048+1024+256+128+4+1 =
3461.
Comme tout est codé sur 5 bits, on a également que le code de CLE est égal
à 3 ∗ 322 + 12 ∗ 321 + 5 ∗ 320 .
Si l’on veut des entiers entre 0 et 100, on doit prendre comme diviseur 101.
L’adresse de CLE est alors ici égale à 3461 modulo 101 = 27.
1.1.3
Que se serait-il passé si l’on avait voulu des entiers entre 0 et 31 ?
Le code utilisé affecte un entier codé sur 5 bis. Ainsi, CLE = 3 ∗ 322 + 12 ∗
1
32 +5∗320 . Le résultat du modulo 32 ne concerne alors que le dernier caractère
de la clé, le rendant non aléatoire.
Un moyen simple d’enlever cette difficulté est de ne considérer que des nombres premiers pour l’opération modulo.
1.1.4
En utilisant la méthode de Horner (cf. première petite classe) proposez un algorithme permettant de calculer l’adresse d’une chaı̂ne de
caractère en utilisant le code précédant (où le code de CLE est égal
à 3 ∗ 322 + 12 ∗ 321 + 5 ∗ 320 ) et la fonction d’adressage égale au modulo.
On
Prappelle que la méthode de Horner consiste à écrire un polynôme P (x) =
a0 + 1≤i≤n ai xi de la façon suivante : P (x) = a0 + x(a1 + ...x(an−1 + an x)...).
Pour notre codage, soit une chaı̂ne de caractère c = c1 c2 . . . cm , et φ la
fonction qui a chaque caractère rend sa position dans l’alphabet.
Le code associé à la chaı̂ne de caractère est alors PC (32) où
X
Pc (x) =
φ(ci−1 )xi
0≤i≤m−1
2
En s’inspirant fortement de la PC1, on a alors l’algorithme 2 qui rend bien
l’adresse de toute chaı̂ne de caractère. On peut remarquer que ceci permet
d’échapper au dépassements d’entiers qui résulterait du codage d’une très longue
chaı̂ne de caractère grâce aux propriétés de la fonction modulo (a*b modulo k’
= (a modulo k’)*(b modulo k’) modulo k’.
Algorithme 2 Calcul d’adresse
Données
une chaine c = c1 c2 . . . cm de m caractères
un entier k’
Début
res=0
pour i=1 a m faire
res=(32*res + φ(ci )) modulo k’
rendre res
Fin
1.2
Fonction d’adressage et dictionnaire
Les fonctions d’adressages sont utilisées dans les structures de données appelées
dictionnaires.
Un dictionnaire peut être vu comme un tableau auquel on accède non pas
par des indices, mais par des chaı̂nes de caractères.
1.2.1
En supposant qu’il existe une fonction d’adressage rendant une adresse
unique quelque soit la chaı̂ne de caractère, proposez une implémentation d’un dictionnaire. Une telle fonction existe-t-elle ? La méthode
est-elle réalisable ?
Il suffit de considérer un tableau dont l’indice correspond à l’adresse de la
chaı̂ne de caractère. Une telle fonction d’adressage existe, il suffit de prendre comme adresse le code associé à chaque chaı̂ne de caractère de la section
précédente.
Une telle méthode est bien évidemment irréalisable en pratique puisque l’on
ne possède pas de mémoire infinie. Mettre en place un dictionnaire nécessite
donc de gérer les chaı̂nes de caractères ayant même adresse.
1.2.2
Comment gérer les chaı̂nes ayant même adresse ?
Le plus simple est qu’à chaque adresse, on utilise une liste contenant les
différentes chaı̂nes de caractères. Ainsi, lorsque deux chaı̂nes possèdent la même
adresse, on peut grâce à la liste savoir si la chaı̂ne est déjà présente. Si la fonction
3
d’adressage est bien “aléatoire”, les listes associées à chaque adresse seront de
longueurs équivalentes.
1.2.3
Quel est l’intérêt d’utiliser ce genre de structure ?
Tout d’abord, utiliser des structures indexées par des chaı̂nes de caractères
se révèle utile dans de nombreuses situations (gérer un carnet d’adresse par
exemple), mais surtout, permet de diviser par le nombre d’adresses différentes
le coût de la recherche d’une chaı̂ne particulière par rapport au coût que l’on
aurait si l’on avait utilisé une unique liste pour stocker les dites chaı̂nes.
2
Algorithme de Rabin-Karp
L’algorithme de Rabin-Karp pour la recherche d’un motif de longueur m dans
une chaı̂ne de caractères c1 revient à considérer une fonction d’adressage et de
vérifier, pour chaque paquet de m lettres de c1 si l’adresse correspond à celle du
motif.
On considérera ici que nombre associé à chaque caractère est sa position
dans l’alphabet, codé en base d. Dans la partie précédente, d était égal à 32.
De même on considère que la fonction d’adressage est la fonction modulo
appliquée à un grand nombre premier q.
2.1
On considère que l’on a une fonction φ rendant pour chaque caractère
sa position dans l’alphabet. Quelle est le code du mot de longueur m
présent à la position i de la chaı̂ne c1 ?
En utilisant l’écriture sous forme de polynôme vue dans la partie précédente,
ce mot s’écrit :
x = φ(c1 [i])dm−1 + φ(c1 [i + 1])dm−2 + . . . + φ(c1 [i + m − 1])d0
2.2
En connaissant le code du mot de longueur m présent à la position i
de la chaı̂ne c1 , quelle est le code du mot de longueur m présent à la
position i+1 de la chaı̂ne c1 ?
(x − φ(c1 [i])dm−1 )d + φ(c1 [i + m])
2.3
En connaissant l’adresse du mot de longueur m présent à la position
i (c’est à dire l’adresse du code du mot) de la chaı̂ne c1 , quelle est
4
l’adresse du mot de longueur m présent à la position i+1 de la chaı̂ne
c1 ?
On utilise la même propriété du modulo que dans la partie précédente pour
résoudre cette question.
On note y = dm−1 modulo q, et x le code du mot de longueur m présent à
la position i de la chaı̂ne c1 . L’adresse de x est alors x modulo q.
de là, l’adresse du mot de longueur m présent à la position i+1 est alors
égale à :
((((x modulo q) + (d ∗ q − φ(c1 [i]) ∗ y)) modulo q) ∗ d + φ(c1 [i + m])) modulo q
Une quantité d*q est ajoutée pour garantir le fait que tout reste bien positif
dans le calcul des modulos.
2.4
En déduire un algorithme permettant de trouver dans une chaı̂ne de
longueur n la première position i dont le mot de longueur m commençant à cette position à la même adresse qu’un motif de longueur
m. Quel est sa complexité ?
La complexité de cette algorithme est clairement O(m + n) (une première
itération de longueur m pour calculer l’adresse du motif et du mot commençant
en position 0, puis une itération de longueur n pour trouver l’appariement).
2.4.1
Que reste-t-il à faire pour trouver un motif dans une chaı̂ne de caractère ?
Il faut encore vérifier que les deux mots sont identiques, puisque deux chaı̂nes
différentes peuvent avoir même adresse. Si l’on considère un entier q très grand
et premier, on va pouvoir limiter au maximum ce risque, rendant l’algorithme
complet presque sûrement linéaire.
5
Algorithme 3 Algorithme de Rabin-Karp
Données
une chaine c1 de n caractères
une chaine c2 de m caractères
une fonction φ, un entier d et q
Début
y=1
pour i=1 a m-1 faire
(calcul de dm−1 modulo q)
y = d*y modulo q
h1 = 0
h2 = 0
pour i=0 a m-1 faire
(calcul de l’adresse de c2 et du mot de longueur m en position 0 de c1 )
h2 = (h2 ∗ d + φ(c2 [i])) modulo q
h1 = (h1 ∗ d + φ(c1 [i])) modulo q
i=0
tant que h1 6= h2 faire
h2 = (h2 + d ∗ q − φ(c1 [i]) ∗ y) modulo q
h2 = (h2 ∗ d + phi(c1 [i + m])) modulo q
Si i > n − m alors
rendre -1
rendre i
Fin
6
Téléchargement