Trouver des anagrammes intéressantes

31

Supposons que et b 1 b 2b 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 .a1a2anb1b2bnp:[1n][1n]ai=bp(i)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 , 1a=b=cababp1[1,2,3,4,5][4,5,1,2,3] , entre autres.p2[1,2,3,4,5][2,5,1,4,3]

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 ( pw(p)pi[1n1]p(i)+1p(i+1)p et w ( p 2 ) = 4 , car p 1 coupeune fois, en morceauxet, et p 2 coupequatre fois, en cinq morceaux.w(p1)=1w(p2)=4p11234512345p212345

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.)ab

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, duedenoet les stomysections, 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.

Mark Dominus
la source
O(n2)
4
Non bien sûr que non. Vous convertissez chaque mot en une forme canonique qui a les mêmes lettres dans l'ordre alphabétique. (Par exemple, la forme canonique de cholecystoduodenostomyest ccddeehlmnooooossttuyy.) 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.
Mark Dominus
J'ai maintenant une grande quantité d'informations plus ou moins liées à ce sujet sur mon blog: (α) (β) (γ) (δ)
Mark Dominus

Réponses:

21

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 AB ≤ 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

Tsuyoshi Ito
la source
J'ai posté un suivi .
Mark Dominus
9

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.

G(i,j)ai=bjai+1=bj+1(i,j)(k,)ikiji+1j+1kk+1+1

  1. i=kj
  2. i+1=kj+1
  3. i+1<k{j,j+1}{,+1}

Gsns1nabG

yttrioustouristyouriououriris=2y|t|t|ri|ou|st|ou|ri|s|t|y

En revanche, considérez derateret treader. Cette fois, le graphique a trois sommets:

  1. DErater + treaDEr
  2. dERater + treadER
  3. deratER + treadER

s=2der|a|t|e|rt|r|e|a|der

Mark Dominus
la source
2
Merci pour le post de suivi, mais ce n'est pas une preuve de NP-exhaustivité de votre problème. Pour prouver l'exhaustivité NP de votre problème, vous devez réduire un problème NP-complete connu à votre problème, et c'est le théorème 2.2 de [GKZ05]. Ce que vous avez présenté ici (Lemme 1.1 de [GKZ05]) est une réduction en sens inverse.
Tsuyoshi Ito
C'est une belle reformulation. Un changement trivial qui est une simplification conceptuelle mineure (au moins pour moi): au lieu de tracer des arêtes entre des paires incompatibles et de demander le jeu indépendant maximum, nous pouvons tracer des arêtes entre des paires qui sont compatibles et demander la clique maximale. (Je trouve plus facile de penser à "quel est le nombre maximum de paires que nous pouvons garder ensemble".)
ShreevatsaR
2

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.

wren romano
la source
0

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 :

  • ()
  • (1)
  • (12)
  • (123)
  • et cetera

Ces «cycles» simples sont composés pour décrire des permutations plus complexes.

n

  • (12)
  • (a b)(a+1 b+1)a>0b<a+1b+1n
  • ...
  • (a b)(a+1 b+1)(a+i1 b+i1)a>0a+i1bb+i1n

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é.)

Dave Clarke
la source
1
Merci. Je suis peut-être pessimiste, mais il me semble que cette approche va être difficile. Je ne pense pas qu'une approche de groupe-théorie portera ses fruits à moins que nous ne découvrions d'abord quel groupe de permutation est d'intérêt, et cela varie en fonction des chaînes d'entrée. Je pense que la représentation efficace des groupes finis est un problème extrêmement profond et riche. Mais je voudrais me tromper.
Mark Dominus
1
«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 pense pas que ce soit correct. Par exemple, si n = 4, le swap (1 2) a un poids 2, mais le swap (2 3) a un poids 3. Votre façon de compter ne les distingue pas.
Tsuyoshi Ito
J'ai répondu tard dans la nuit. Je n'ai pas bien compris la mesure du poids. En fait, je ne le comprends pas maintenant. Je pensais que vous vouliez autoriser les déplacements de blocs de lettres, c'est pourquoi je me suis donné la peine de définir ces primitives. Ma réponse pourrait être une source d'inspiration, alors je vais la laisser, même si elle est fausse.
Dave Clarke
0

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?

Dan Gelder
la source