6
votes

Question de mappage de chaîne et de caractère pour le gourou

Voici un problème qui m'a été soulevé (Solution Wise):

donné un STR S , appliquer des mappages de caractères cm = {A = (m, O, P), D = (q, u), ...} et imprimez toutes les combinaisons possibles à l'aide de C ou C ++.

La chaîne peut être n'importe quelle longueur et le nombre de mappages de caractères varie, et là-bas. Ne serez pas des mappages qui plantent vers une autre carte (évitant ainsi les dépendances circulaires).

comme exemple: chaîne abba avec mappages a = (e, o) , d = (g, h), b = (i) imprimerait: xxx


6 commentaires

Nope pas de devoirs, aidant une équipe avec une vie réelle livrable avec une date limite serrée. Je suis un gars intégré du double e, non familiarisé avec les structures de données, ect ... toute aide serait appréciée, même un point à la tête dans une direction spécifique. Je pensais récursif, mais cela ne se sent pas bien.


@Gio: OK, quelle est la longueur maximale de la cartographie? Sont-ils fixés, soit 2 mappages possibles? Comme dans votre exemple ci-dessus?


Max String Longueur = 32, Nombre maximum de mappages = 8, Nombre maximum de caractères par carte = 4. Évidemment, non pas en pierre car il y a des personnes marketing impliquées ... Soupir. Ainsi, les indices d'algorithme seraient les plus appréciés. Nous pouvons nous occuper des problèmes de mémoire ou d'autres modifications nécessaires. À une réunion.


Gio: +1 De moi ... Vérifiez ma réponse ci-dessous pour voir si cela est réalisable / viable ... Je suppose que vous pourriez filtrer ceux qui ne sont pas dans la cartographie ... ??


Êtes-vous prêt à obtenir des milliards de chaînes? Si chaque caractère d'une chaîne a une autre, une chaîne de 32 caractères générera plus de quatre milliards de chaînes.


Eh bien, mon programme génère 612 millions de chaînes en 6,1 secondes sur un duo 2.2GHz Core2, entrée 'AEO DGH BI' ABDABDABDABDABDABDABD .


6 Réponses :


0
votes

Vous voulez essentiellement faire une première recherche de profondeur (DFS) ou toute autre traversée dans un graphique de mot acyclique dirigé (DAWG). Je vais poster du code sous peu.


0 commentaires

1
votes

La façon dont je voudrais y aller est de créer une gamme d'index de la même longueur que la chaîne, toutes initialisées à zéro. Nous traitons ensuite cette gamme d'index comme compteur pour énumérer tous les mappages possibles de notre chaîne source. Une carte d'index de 0 position dans la chaîne à la première cartographie pour ce caractère, a 1 à la seconde, etc. Nous pouvons les parcourir dans l'ordre en incrémentant simplement le dernier index dans le tableau, avec la position suivante lorsque nous atteindre le nombre maximum de mappages pour cette position.

Pour utiliser votre exemple, nous avons les mappages xxx

avec la chaîne d'entrée "ABBA", nous avons besoin d'un élément de quatre éléments. tableau pour nos index: xxx

Avant de commencer à générer ces chaînes, nous aurons besoin d'un endroit pour les stocker, ce qui signifie que nous sommes va avoir à allouer de la mémoire. Heureusement, nous connaissons déjà la longueur de ces chaînes et nous pouvons comprendre Le nombre de chaînes que nous allons générer - c'est juste le produit du nombre de mappages pour chaque position.

pendant que vous pouvez les renvoie dans un tableau , je préfère utiliser un rappel pour les retourner comme je les trouve. xxx


3 commentaires

Pendant que cela fonctionne, il me fait toujours de voir masloc et gratuit partout, surtout lorsqu'il n'est pas jumelé dans la même méthode ... aussi (mais c'est typique avec English -lers) Certains Char peuvent avoir une valeur négative (pour les caractères accentués dans l'ASCII étendu).


Merci de m'avoir appelé à l'aide de caractères signés comme index des array. Corrigé ça. En ce qui concerne le retour de la mémoire allouée - je préfère que l'appelant affecte la mémoire, mais dans des cas comme celle-ci, où la mémoire de la mémoire allouée est une grande partie du calcul, il semble idiot de s'attendre à ce que l'appelant puisse s'attendre à ce que l'appelant puisse comprendre.


En fait, savez quoi? Je vais réécrire cela avec un rappel, car j'aime mieux ça.



2
votes

Certainement possible, pas vraiment difficile ... mais cela générera de nombreuses chaînes qui sont sûres.

La première chose à remarquer est que vous savez combien de cordes il va générer à l'avance, il est donc facile de faire certains Vérification de la santé mentale:) p>

La seconde: il ressemble à une solution récursive serait facile (comme de nombreux problèmes de traversée). p> xxx pré>

et voici la sortie : P>

Original: abba
Mapped: {'a': 'eo''b': 'i''d': 'gh'}
Generated:
  abba
  abbe
  abbo
  abia
  abie
  abio
  aiba
  aibe
  aibo
  aiia
  aiie
  aiio
  ebba
  ebbe
  ebbo
  ebia
  ebie
  ebio
  eiba
  eibe
  eibo
  eiia
  eiie
  eiio
  obba
  obbe
  obbo
  obia
  obie
  obio
  oiba
  oibe
  oibo
  oiia
  oiie
  oiio


0 commentaires

0
votes

Il y a un lien vers l'archive des extraits qui fait cela, ici, Permute2 .c . Il y a une autre variante de la permutation de chaîne (je suppose que vous pourriez alors filtrer ceux qui ne sont pas sur la carte!) Voir ici sur le ' SNIPPETS 'Archive ...

J'espère que cela aide, Meilleures salutations, Tom.


0 commentaires

2
votes

Edit: strong> Cela devrait être l'algo la plus rapide et le plus simple possible possible. Certains peuvent discuter avec le style ou la portabilité; Je pense que c'est parfait pour une chose de type embarqué et j'ai déjà passé suffisamment longtemps dessus. Je quitte l'original ci-dessous.

Ceci utilise un tableau pour la cartographie. Le bit de signalisation est utilisé pour indiquer la fin d'un cycle de cartographie, de sorte que le type de mappage doit être supérieur au type mappé si vous souhaitez utiliser la plage complète non signée code>. P>

P> Génère des chaînes de 231 m / sec ou ~ 9.5 cycles / chaîne sur un noyau 2.2GHz2. Conditions de test et utilisation comme ci-dessous. P>

#include <iostream>
#include <algorithm>
using namespace std;

enum { alphabet_size = UCHAR_MAX+1 };

struct MapNode {
     MapNode *next;
     char c;
     bool last;
     MapNode() : next( this ), c(0), last(false) {}
};

void CreateMap( string s, MapNode (&m)[ alphabet_size ] ) {
    MapNode *mprev = 0;
    replace( s.begin(), s.end(), ' ', '\0' );
    char *str = const_cast<char*>(s.c_str()), *str_end = str + s.size() + 1;
    for ( char *pen = str; pen != str_end; ++ pen ) {
        if ( mprev == 0 ) sort( pen, pen + strlen( pen ) );
        if ( * pen == 0 ) {
            if ( mprev ) mprev->last = true;
            mprev = 0;
            continue;
        }
        MapNode &mnode = m[ * pen ];
        if ( mprev ) swap( mprev->next, mnode.next ); // link node in
        mnode.c = * pen; // tell it what char it is
        mprev = &mnode;
    }
       // make it easier to tell that a node isn't in any map
    for ( MapNode *mptr = m; mptr != m + alphabet_size; ++ mptr ) {
        if ( mptr->next == mptr ) mptr->next = 0;
    }
}

bool NextMapping( string &s, MapNode (&m)[ alphabet_size ] ) {
    for ( string::iterator it = s.begin(); it != s.end(); ++ it ) {
        MapNode &mnode = m[ * it ];
        if ( mnode.next ) {
            * it = mnode.next->c;
            if ( ! mnode.last ) return true;
        }
    }
    return false;
}

int main( int argc, char **argv ) {
    MapNode m[ alphabet_size ];
    CreateMap( argv[1], m );
    string s = argv[2];
    do {
        cerr << s << endl;
    } while ( NextMapping( s, m ) );
 return 0;
}
  • nécessite que la chaîne d'entrée contienne toujours la première lettre alphabétique de chaque ensemble de remplacement li>
  • Exécutez une LA CarteTool 'AEO DGH BI' ABBD CODE> LI>
  • la sortie est dans l'ordre inverse-lexicographique li>
  • Performance d'environ 22 cycles / chaîne (cordes de 100 m / sec à 2,2 GHz Core2)
    • Mais ma plate-forme essaie d'être intelligente avec string code> s, ralentissez-le vers le bas li>
    • Si je le change pour utiliser Char * CODE> Strings, il fonctionne à la place à Strings de 142m de 142m / sec Strong> (~ 15.5 cycles / string) Li> ul> li>
    • devrait être possible d'aller plus vite à l'aide d'un Char [256] Code> Tableau de mappage et d'un autre Char [256] Code> Spécifier quels caractères finissent par le cycle. LI> ul>

      La structure de données cartographiques est une matrice de nœuds liés dans des listes circulaires. P>

      #include <iostream>
      using namespace std;
      
      int const alphabet_size = CHAR_MAX+1;
      typedef int map_t; // may be char or short, small performance penalty
      int const sign_bit = 1<< CHAR_BIT*sizeof(map_t)-1;
      typedef map_t cmap[ alphabet_size ];
      
      void CreateMap( char *str, cmap &m ) {
          fill( m, m+sizeof(m)/sizeof(*m), 0 );
          char *str_end = strchr( str, 0 ) + 1;
          str_end[-1] = ' '; // space-terminated strings
          char prev = ' ';
          for ( char *pen = str; pen != str_end; ++ pen ) {
              if ( * pen == ' ' ) {
                  m[ prev ] |= sign_bit;
                  prev = 0;
              }
              m[ * pen ] = * pen;
              if ( prev != ' ' ) swap( m[prev], m[ *pen ] );
              prev = *pen;
          }
          for ( int mx = 0; mx != sizeof(m)/sizeof(*m); ++ mx ) {
              if ( m[mx] == 0 ) m[mx] = mx | sign_bit;
          }
      }
      
      bool NextMapping( char *s, char *s_end, cmap &m ) {
          for ( char *pen = s; pen != s_end; ++ pen ) {
              map_t oldc = *pen, newc = m[ oldc ];
              * pen = newc & sign_bit-1;
              if ( newc >= 0 ) return true;
          }
          return false;
      }
      
      int main( int argc, char **argv ) {
          uint64_t cnt = 0;
          cmap m;
          CreateMap( argv[1], m );
          char *s = argv[2], *s_end = strchr( s, 0 );
          do {
              ++ cnt;
          } while ( NextMapping( s, s_end, m ) );
          cerr << cnt;
          return 0;
      }
      


0 commentaires

0
votes

Permis simple et récursif, avec l'utilisation de Char Carte [256]

char *map [256];

/* permute the ith char in s */
perm (char *s, int i)
{
   if (!s) return;

   /* terminating condition */
   if (s[i] == '\0') {
      /* add "s" to a string array if we want to store the permutations */
      printf("%s\n", s);
      return;
   }

   char c = s[i];
   char *m = map [c];
   // printf ("permuting at [%c]: %s\n", c, m);
   int j=0;
   /* do for the first char, then use map chars */
   do {
      perm (s, i+1);
      s[i] = m[j];
   } while (m[j++] != '\0');
   /* restore original char here, used for mapping */
   s[i] = c;

   return;
}

int main ()
{
   /* map table initialization */
   map['a'] = "eo\0";
   map['b'] = "i\0";
   map['d'] = "gh\0";

   /* need modifyable sp, as we change chars in position, sp="abba" will not work! */
   char *sp = malloc (10);
   strncpy (sp, "abba\0", 5);

   perm (sp, 0);
   return 0;
}


0 commentaires