Supposons que et b 1 b 2 … b n sont deux chaînes de même longueur. Une anagrammation de deux chaînes est une cartographie bijective p : [ 1 … n ] → [ 1 … n ] telle que a i = b p ( i ) pour chaque i .
Il peut y avoir plusieurs anagrammes pour la même paire de chaînes. Par exemple, si `abcab` et b = nous avons p 1 [ 1 , 2 , 3 , 4 , 5 ] → [ 4 , 5 , 1 , 2 , 3 ] et p 2 [ 1 , 2 , 3 , 4 , 5 ] → [ 2 , 5 , 1cabab
, entre autres.
Nous dirons que le poids d'une anagramme p est le nombre de coupes que l'on doit faire dans la première chaîne pour obtenir des morceaux qui peuvent être réarrangés pour obtenir la deuxième chaîne. Formellement, c'est le nombre de valeurs de i ∈ [ 1 … n - 1 ] pour lesquelles p ( i ) + 1 ≠ p ( i + 1 ) . C'est-à-dire que c'est le nombre de points où p n'augmente pas exactement de 1. Par exemple, w ( p et w ( p 2 ) = 4 , car p 1 coupeune fois, en morceauxet, et p 2 coupequatre fois, en cinq morceaux.12345
123
45
12345
Supposons qu'il existe une anagramme pour deux chaînes et b . Ensuite, au moins une anagramme doit avoir le moins de poids. Disons que celui-ci est le plus léger . (Il peut y avoir plusieurs anagrammes les plus légers; je m'en fiche parce que je ne m'intéresse qu'aux poids.)
Question
Je veux un algorithme qui, étant donné deux chaînes pour lesquelles une anagramme existe, donne efficacement le poids exact de l'anagramme le plus léger des deux chaînes. Ce n'est pas grave si l'algorithme donne également une anagramme la plus légère, mais ce n'est pas nécessaire.
C'est assez simple de générer tous les anagrammes et de les peser, mais il peut y en avoir beaucoup, donc je préférerais une méthode qui trouve directement les anagrammes légers.
Motivation
La raison pour laquelle ce problème est intéressant est la suivante. Il est très facile de faire rechercher dans le dictionnaire l'ordinateur et de trouver des anagrammes, des paires de mots qui contiennent exactement les mêmes lettres. Mais beaucoup d'anagrammes produites sont sans intérêt. Par exemple, les exemples les plus longs que l'on trouve dans le deuxième dictionnaire international de Webster sont:
cholécystoduodénostomie
duodénocholécystostomie
Le problème devrait être clair: ce sont sans intérêt car ils admettent un anagramming très léger que le simple échange de la cholecysto
, duedeno
et les stomy
sections, pour un poids de 2. D'autre part, cet exemple beaucoup plus court est beaucoup plus surprenant et intéressant:
sectionnel littoral
Ici, l'anagramme le plus léger a un poids de 8.
J'ai un programme qui utilise cette méthode pour localiser des anagrammes intéressantes, à savoir celles pour lesquelles toutes les anagrammes sont de poids élevé. Mais il le fait en générant et en pesant tous les anagrammes possibles, ce qui est lent.
cholecystoduodenostomy
estccddeehlmnooooossttuyy
.) Deux mots sont des anagrammes si et seulement s'ils ont la même forme canonique. Vous stockez les mots dans une table de hachage, saisis par leurs formes canoniques, et chaque fois que vous trouvez une collision, vous avez une anagramme.Réponses:
Ce problème est connu sous le nom de «problème de partition de chaîne commune minimale». (Plus précisément, la réponse dans le problème de partition de chaîne commune minimale est égale à la réponse dans votre problème plus 1.) Malheureusement, il est NP-difficile, même avec la restriction que chaque lettre apparaît au maximum deux fois dans chacune des chaînes d'entrée, comme le prouvent Goldstein, Kilman et Zheng [GKZ05]. Cela signifie qu'aucun algorithme de temps polynomial n'existe sauf si P = NP. (Bien sûr, si chaque lettre apparaît au plus une fois, le problème est trivial car il n'y a qu'une seule anagramme.)
Du côté positif, les mêmes auteurs [GKZ05] donnent un algorithme d'approximation du temps polynomial 1.1037 sous la même restriction. (Un « algorithme d'approximation 1.1037 » signifie un algorithme qui peut ne pas produire la bonne réponse A mais qui est garanti de produire une valeur B telle que A ≤ B ≤ 1.1037 A. ) Ils donnent également un algorithme d'approximation à temps linéaire 4 sous restriction plus faible selon laquelle chaque lettre apparaît au maximum trois fois dans chacune des chaînes d'entrée.
[GKZ05] Avraham Goldstein, Petr Kolman et Jie Zheng. Problème de partition de chaîne commune minimale: dureté et approximations. Electronic Journal of Combinatorics , 12, article R50, 2005. http://www.combinatorics.org/ojs/index.php/eljc/article/view/v12i1r50
la source
Ceci fait suite à la réponse de Tsuyoshi Ito ci - dessus , résumant la partie la plus pertinente du document GKZ05 qu'il a citée.
yttrious
touristy
ou
ri
ou
ou
ri
ri
y|t|t|ri|ou|s
t|ou|ri|s|t|y
En revanche, considérez
derater
ettreader
. Cette fois, le graphique a trois sommets:DErater
+treaDEr
dERater
+treadER
deratER
+treadER
der|a|t|e|r
t|r|e|a|der
la source
Il ne couvre pas l'algorithme exact que vous aviez en tête (ce que fait la réponse de Tsuyoshi Ito ), mais en essayant de résoudre le problème sous-jacent de trouver des anagrammes "intéressantes" ...
Ma première pensée a été d'utiliser une variation sur la distance d'édition, où les changements atomiques sont pondérés en fonction de leur "intérêt" plutôt que des pondérations habituelles de "difficulté" ou de "confusion". Bien sûr, il semble peu probable que vous puissiez encoder efficacement les transformations vraiment intéressantes de cette manière, car elles sont susceptibles d'être non locales et donc de rencontrer les problèmes NP-complets de MIS, etc.
Donc, la deuxième pensée serait de construire un alignement de lettre à lettre entre les mots (alignements à la traduction automatique), puis de marquer les alignements eux-mêmes pour leur "intérêt" (par exemple, en comptant les alignements qui prennent des lettres adjacentes vers des caractères non lettres adjacentes, ou combien d'alignements chaque alignement traverse, etc., puis combinez-les tous via un modèle log-linéaire ou autre).
La troisième idée est d'abandonner complètement de regarder la structure de l'anagramme elle-même, et de regarder plutôt la sémantique des mots. Souvent, ce qui rend une anagramme "intéressante", c'est l'incongruité entre les significations des mots impliqués. Essayez donc quelque chose comme calculer leur distance dans WordNet, ou similaire.
la source
Le problème peut être exprimé en termes de groupes de permutation .
Désormais, un groupe de permutation contient tous les "mouvements d'anagramme", à la fois primitifs (échange de deux lettres) et composites de séquences de mouvements primitifs. Il semble que vous ne vous intéressiez qu'à un sous-ensemble des permutations possibles. Je vais essayer de les définir.
Rappelons d'abord la notation des permutations, à savoir la notation dite de cycle :
Ces «cycles» simples sont composés pour décrire des permutations plus complexes.
Ces mouvements constituent la base de votre algorithme. Ce qui vous intéresse, c'est de trouver la plus petite séquence de ces mouvements pour passer d'un mot à l'autre.
Je ne connais aucun algorithme pour le calculer, à part la recherche par force brute, mais au moins maintenant il y a une description plus claire (j'espère) de ce que sont les mouvements primitifs. (Et peut-être qu'un théoricien de groupe parmi nous peut indiquer un algorithme approprié.)
la source
Pour la cholécystoduodénostomie / duodénocholécystostome, je remarque que si vous attribuez un numéro à chaque caractère décrivant combien il a été déplacé en tant que delta, vous auriez quelque chose comme 7 7, puis 8 -7, puis 6 0. Ce n'est pas correct car certains caractères peuvent avoir été répétés (le deuxième c n'a avancé que de 2, pas en arrière de 7), etc. mais reste très "codé en longueur" car vous voyez les mêmes deltas d'affilée.
Comparez avec le littoral / sectionnel, où vous voyez quelque chose comme (+2) (+ 5) (+ 5) (- 3) (- 1) (+ 3) .... beaucoup moins "run length encodable".
Peut-être que le caractère aléatoire des deltas pourrait vous donner un "score" quant à l'intérêt de l'anagramme?
la source