• Aucun résultat trouvé

Table des suffixes et des plus long préfixes communs

Définition 6.6. (Ordre lexicographique) Soit Σ l’alphabet des lexèmes manipulés muni d’un ordre total <. Nous définissons l’ordre lexicographique <lex dérivé de < sur les chaînes de Σ∗

ainsi : pour tout couple (u, v) de Σ∗, u <

lex v ssi il existe (x, y, z) ∈ Σ∗3 avec la décomposition

u = x · y et v = x · z telle que y[1] < z[1] (par convention ǫ[1] = ǫ et pour tout a ∈ Σ, ǫ ≤ a). x est le plus long préfixe commun de u et v.

Définition 6.7. (Table des suffixes) La table des suffixes SA (T ) (en anglais Suffix Array) de l’ensemble des chaînes de lexèmes T est la suite d’occurrences de suffixes de T triées par ordre lexicographique (chaque occurrence de suffixe étant représentée par le couple (i, j), i étant l’indice de la chaîne ti, j l’indice de début du suffixe dans la chaîne).

Définition 6.8. (Table inverse des suffixes) La table inverse des suffixes rSA (T ) de l’ensemble des chaînes de lexèmes T est la table faisant correspondre chaque occurrence de suffixe Ti[j]

avec sa position dans la table de suffixes SA (T ).

Il découle de la définition de la table des suffixes que si l’on considère un arbre de suffixes (dont les enfants de chaque nœud sont triées par premier lexème du nœud), la table des suffixes est obtenue par un parcours en profondeur de l’arbre en ne conservant que ses nœuds p avec |t(p)| > 0. Il est donc immédiat d’obtenir la table de suffixes à partir de l’arbre de

6.3. Table des suffixes et des plus long préfixes communs 96

suffixes en temps linéaire du nombre de suffixes. Réciproquement, il est également possible de construire l’arbre des suffixes à partir de la table des suffixes (cf section 6.4). Nous étudions des algorithmes de construction directe de la table de suffixes, mémoriellement plus intéressants. 6.3.2 Construction de la table de suffixes

Algorithme original de doublement Manber et Myers introduisirent [35] la structure de table de suffixes avec un algorithme de construction de complexité temporelle en O(L log lmax)

pour des chaînes de longueur cumulée L avec une chaîne de longueur maximale lmax. Le

principe de la construction repose sur le constat suivant : s’il est possible de trier tous les préfixes de suffixes de longueur k, nous pouvons considérer tous les préfixes de suffixes de longueur 2k comme les concaténations de deux préfixes consécutifs de suffixes de longueur k. Ainsi nous pouvons écrire la chaîne t comme la concaténation de chaînes de longueur k : t = c1c2· · · c|c|/k (|c1| = |c2| = · · · = |c|c|/k|)3. Connaissant le classement lexicographique des

facteurs c1, c2, · · · , c|c|/k, nous en déduisons en temps O(|c|/k) le classement lexicographique

des couples c1c2, c2c3, · · · , c|c|/k−1c|c|/kpar un tri par bacs. En conséquence, nous obtenons le

classement des préfixes de suffixes de longueur 2k. Ce processus de doublement de la taille des préfixes de suffixes triés débute par le classement des lexèmes unitaires et se termine à l’itération f lorsque les préfixes de suffixes de taille 2f sont tous distincts. La complexité

temporelle est donc dépendante de la taille r des plus grands facteurs répétés (O(L log r), r ≤ lmax).

Algorithmes en temps linéaire La table de suffixes d’un ensemble de chaînes (de lon- gueurs cumulées) peut être construite simplement en temps O(L) à partir du parcours des feuilles de l’arbre de suffixes correspondant construit lui-même en temps linéaire. La première méthode de construction directe en temps linéaire, dite skew, a été proposée par Kärkkäinen et Sanders [31]. Celle-ci procède en trois étapes principales : la première consiste à trier les deux tiers des suffixes de position 1 mod 3 et 2 mod 3 (on suppose le premier caractère d’indice 0) tandis que lors de la deuxième étape, les suffixes de position 0 mod 3 sont comparés avec l’ensemble des suffixes précédemment triés. Enfin, la troisième étape permet de trier par fusion les suffixes de position {1, 2} mod 3 et les suffixes de position 0 mod 3. Le tri des suffixes est appliqué récursivement sur les suffixes de position {1, 2} mod 3 en remplaçant ces suffixes par les 3-grams débutant à ces positions et en triant les suffixes de la chaîne ainsi obtenue. La connaissance de l’ordre des suffixes de positions {1, 2} permet un tri et la fusion en temps O(L) des suffixes de position 0 mod 3. Finalement l’algorithme peut être mené en temps T (L) = O(L) + T (23L) = O(L) avec un tri par bacs des k-uplets de lexèmes ou k-grams. Cela implique l’utilisation d’un alphabet énumérable. Dans le cas contraire (qui ne nous intéresse cependant pas pour nos applications), le tri des suffixes nécessite une complexité temporelle minimale de O(L log L).

Comparaison des algorithmes D’autres algorithmes ont été proposés chacun avec leurs spécificités : privilégiant les chaînes avec des faibles répétitions, de longues répétitions ou tentant de réduire l’espace mémoire nécessaire pour la construction. L’algorithme skew de Kärkkäinen et Sanders [31] bien qu’étant de complexité linéaire dans le pire des cas ne permet pas les implantations les plus rapides, comme le montrent les tests présentés par [39]. Des

3

algorithmes de complexité temporelle dans le pire des cas équivalente à un tri naïf des suffixes (Θ(n2logn)) peuvent présenter des résultats expérimentaux temporellement et mémoriellement

avantageux [37].

6.3.3 Table des plus longs préfixes communs

Afin de pouvoir localiser les suffixes présentant un préfixe commun de longueur impor- tante (facteurs répétés), nous nous intéressons à la longueur des préfixes communs de suffixes consécutifs de la table des suffixes.

Définition 6.9. Soient deux chaînes u et v. w est le plus long préfixe commun de u et v ssi il existe des factorisations u = wu′ et v = wvavec soit u= ǫ, v= ǫ ou u[1] 6= v[1]. On note

w = lcp (u, v).

Définition 6.10. La table des plus long préfixes communs LCP(T ) est la suite finie de taille |SA (T )| dont l’élément d’indice i > 0 est la longueur de lcp (SA (T ) [i − 1], SA (T ) [i]). Par convention LCP(T )[1] = 0.

Une méthode de construction rapide de la table des LCP (introduite par Kasai et al. [32] et présentée en algorithme 1) nécessite la connaissance de la table de suffixes ainsi que de la table inverse de suffixes. L’idée consiste à non pas calculer la table par indice croissant mais par position croissante des suffixes dans leurs chaînes. Sans perte de généralité, nous considérons une unique chaîne de lexèmes u à partir de laquelle est construite la table (directe et inverse) des suffixes. p = rSA u[i] désigne la position du suffixe u[i..] dans la table de suffixes : nous calculons ainsi LCP[p] par comparaison lexème par lexème de SA[p] = u[i..] (p ≥ 2) avec SA[p − 1] = u[h..] (k + 1 comparaisons pour un plus long préfixe commun de taille k). Avec p′ = rSA u[i + 1..] (position du suffixe u[i + 1..]), nous avons LCP[p] ≥ LCP[p] − 1. En

effet LCP[p′] est minimal lorsque le prédécesseur lexicographique de u[i + 1..] dans la table

des suffixes est u[h + 1..] : alors LCP[p′] = LCP[p] − 1. Nous pouvons ainsi calculer avec

2|u| − 1 comparaisons de lexèmes au maximum toutes les valeurs de la table LCP[p] selon le même raisonnement que celui utilisé pour l’algorithme de construction d’arbre de suffixes de McCreight (cf sous-section 6.2.2).

La table des LCP peut être utilisée pour localiser les couples d’occurrences de plus longs facteurs répétés et donc mettre rapidement en évidence les clones les plus substantiels. La recherche exhaustive des facteurs répétés requiert elle le groupement de toutes les occurrences d’un facteur répété pour garantir la complétude : celle-ci peut être menée à partir de la table de suffixes aidée de la table des LCP afin de construire l’arbre des intervalles. Chacun des intervalles de cet arbre correspond à un intervalle de suffixes consécutifs dans la table de suffixes et ainsi à un nœud interne de l’arbre des suffixes.

6.4 Arbre des intervalles et structures associées