Je suis à la recherche d'un algorithme d'appariement rapide de chaînes k-mismatch. Étant donné une chaîne de motif P de longueur m et une chaîne de texte T de longueur n, j'ai besoin d'un algorithme rapide (temps linéaire) pour trouver toutes les positions où P correspond à une sous-chaîne de T avec au plus k mésappariements. Ceci est différent du problème des différences k (distance d'édition). Un décalage implique que la sous-chaîne et le motif ont une lettre différente dans au plus k positions. Je n'ai vraiment besoin que de k = 1 (au plus 1 décalage), donc un algorithme rapide pour le cas spécifique de k = 1 suffira également. La taille de l'alphabet est 26 (texte anglais insensible à la casse), donc l'espace requis ne devrait pas augmenter trop rapidement avec la taille de l'alphabet (par exemple, l'algorithme FAAST, je crois, prend un espace exponentiel dans la taille de l'alphabet, et ainsi de suite). convient uniquement aux séquences de protéines et de gènes).
Une approche basée sur la programmation dynamique aura tendance à être O (mn) dans le pire des cas, ce qui sera trop lent. Je crois qu'il y a des modifications de l'algorithme de Boyer-Moore pour cela, mais je ne suis pas en mesure de mettre la main sur de tels papiers. Je n'ai pas d'abonnement pour accéder aux revues ou publications académiques, donc toutes les références devront être dans le domaine public.
J'apprécierais grandement tous les pointeurs ou références à des documents librement disponibles, ou l'algorithme lui-même pour ce problème.
Réponses:
Les tableaux de suffixes peuvent être utilisés pour ce problème. Ils contiennent les positions de départ de chaque suffixe de la chaîne triées par ordre lexicographique. Même s'ils peuvent être construits naïvement dans la complexité , il existe des méthodes pour les construire dans la complexité . Voir par exemple ceci et cela . Appelons ce tableau de suffixes SA.Θ ( n )O(nlogn) Θ(n)
Une fois que le tableau de suffixes a été construit, nous devons construire un tableau LCP (Longest Common Prefix) pour le tableau de suffixes. Le tableau LCP stocke la longueur du préfixe commun le plus long entre deux préfixes consécutifs dans le tableau de suffixes (suffixes lexicographiques consécutifs). Ainsi, LCP [i] contient la longueur du préfixe commun le plus long entre SA [i] et SA [i + 1]. Ce tableau peut également être construit en temps linéaire: voir ici , ici et ici pour quelques bonnes références.
Maintenant, pour calculer la longueur de la commune le plus long préfixe à tous les deux suffixes dans l'arbre suffixe ( au lieu de suffixes consécutifs), nous avons besoin d'utiliser une RMQ structure de données. Il a été montré dans les références ci-dessus (et peut être vu facilement si le tableau est visualisé comme un arbre de suffixe), que la longueur du préfixe commun le plus long entre deux suffixes ayant des positions et ( ) dans le tableau de suffixes , peut être obtenu sous la forme . Une bonne RMQ peut prétraiter le tableau en temps ou et répondre aux requêtes de la forme dansv u < v m i n u < = k < = v - 1 L C P [ k ] L C P O ( n ) O ( n log n ) L C P [ u , v ] O ( 1 )u v u<v minu<=k<=v−1LCP[k] LCP O(n) O(nlogn) LCP[u,v] O(1) temps. Voir ici pour un algorithme RMQ succint, et ici pour un bon tutoriel sur les RMQ, et la relation (et les réductions) entre LCA et RMQ. Cela a une autre belle approche alternative.
Avec ces informations, nous construisons le tableau de suffixes et les tableaux associés (comme décrit ci-dessus) pour la concaténation des deux chaînes avec un délimiteur entre les deux (comme T # P, où '#' n'apparaît dans aucune chaîne). Ensuite, nous pouvons effectuer k correspondance de chaîne de mésappariement en utilisant la méthode "kangourou". Ceci et cela expliquent la méthode kangourou dans le contexte des arbres de suffixes, mais peuvent également être directement appliqués aux tableaux de suffixes. Pour chaque index du texte , trouvez le du suffixe de commençant à et le suffixe de commençant à 0. Cela donne l'emplacement après lequel le premier décalage se produit lors de la correspondance dei T LCP T i P P avec . Soit cette longueur . Ignorez le caractère incompatible dans et et essayez de faire correspondre les chaînes restantes. Autrement dit, trouvez à nouveau le de et . Répétez cette opération jusqu'à ce que vous obteniez non-concordances ou les finitions de chaîne. Chaque est . Il existe pour chaque indice de , ce qui donne une complexité totale de .T[i] l0 T P LCP T[i+l0+1] P[l0+1] k LCP O(1) O(k) LCP i T O(nk)
J'ai utilisé un RMQ plus facile à implémenter donnant une complexité totale de , ou si , mais il peut aussi être fait en comme décrit ci-dessus. Il peut y avoir d'autres méthodes directes pour ce problème, mais il s'agit d'une approche puissante et générique qui peut être appliquée à de nombreux problèmes similaires.O(nk+(n+m)log(n+m)) O(nk+nlogn) m=O(n) O(nk)
la source
Ci-dessous se trouve un algorithme attendu (qui peut être étendu à d'autres , ce qui en fait ). (Je n'ai cependant pas fait les calculs pour prouver qu'il en est ainsi).O(n+m) k O(nk+m)
L'idée est similaire à l' algorithme de hachage déroulant Rabin-Karp pour les correspondances de sous-chaînes exactes.
L'idée est de séparer chaque chaîne de longueur en blocs de taille et chaque calculer la valeur de hachage pour chaque bloc de roulement (donnant valeurs de hachage) et comparer ces valeurs de hachage contre l'une à partir du motif.m 2k m/2k 2k 2k
Nous autorisons au plus disparités dans ces valeurs.k
Si plus de asymétries se produisent, nous rejetons et passons. Sinon, nous essayons de confirmer une correspondance approximative.k
Je m'attends (mise en garde: je ne l'ai pas essayé moi-même), ce sera probablement plus rapide dans la pratique, et peut-être plus facile à coder / à maintenir, que d'utiliser une approche basée sur un arbre de suffixes.
la source