Mots cycliques
Énoncé du problème
Nous pouvons considérer un mot cyclique comme un mot écrit dans un cercle. Pour représenter un mot cyclique, nous choisissons une position de départ arbitraire et lisons les caractères dans le sens des aiguilles d'une montre. Ainsi, "image" et "turepic" sont des représentations pour le même mot cyclique.
Vous obtenez une chaîne de caractères [], dont chaque élément est une représentation d'un mot cyclique. Renvoie le nombre de mots cycliques différents qui sont représentés.
Victoires les plus rapides (Big O, où n = nombre de caractères dans une chaîne)
Réponses:
Python
Voici ma solution. Je pense qu'il pourrait encore être O (n 2 ), mais je pense que le cas est en moyenne beaucoup mieux que cela.
Fondamentalement, cela fonctionne en normalisant chaque chaîne afin que toute rotation ait la même forme. Par exemple:
La normalisation se fait en recherchant le caractère minimum (par code de caractère) et en faisant tourner la chaîne de sorte que le caractère soit dans la dernière position. Si ce caractère apparaît plus d'une fois, les caractères après chaque occurrence sont utilisés. Cela donne à chaque mot cyclique une représentation canonique, qui peut être utilisée comme clé dans une carte.
La normalisation est n 2 dans le pire des cas (où chaque caractère de la chaîne est le même, par exemple
aaaaaa
), mais la plupart du temps, il n'y aura que quelques occurrences et le temps d'exécution sera plus prochen
.Sur mon ordinateur portable (Intel Atom double cœur à 1,66 GHz et 1 Go de RAM), le faire fonctionner
/usr/share/dict/words
(234937 mots avec une longueur moyenne de 9,5 caractères) prend environ 7,6 secondes.la source
Python (3) à nouveau
La méthode que j'ai utilisée consistait à calculer un hachage déroulant de chaque mot à partir de chaque caractère de la chaîne; comme il s'agit d'un hachage roulant, il faut O (n) (où n est la longueur du mot) pour calculer tous les n hachages. La chaîne est traitée comme un nombre de base-1114112, ce qui garantit que les hachages sont uniques. (Elle est similaire à la solution Haskell, mais plus efficace car elle ne traverse la chaîne que deux fois.)
Ensuite, pour chaque mot d'entrée, l'algorithme vérifie son hachage le plus bas pour voir s'il est déjà dans l'ensemble de hachages vus (un ensemble Python, donc la recherche est O (1) dans la taille de l'ensemble); s'il l'est, alors le mot ou l'une de ses rotations a déjà été vu. Sinon, il ajoute ce hachage à l'ensemble.
L'argument de ligne de commande doit être le nom d'un fichier qui contient un mot par ligne (comme
/usr/share/dict/words
).la source
Haskell
Je ne suis pas sûr de l'efficacité de cela, probablement plutôt mauvais. L'idée est de créer d'abord toutes les rotations possibles de tous les mots, de compter les valeurs qui représentent uniquement les chaînes et de sélectionner le minimum. De cette façon, nous obtenons un nombre unique à un groupe cyclique.
Nous pouvons regrouper par ce numéro et vérifier le nombre de ces groupes.
Si n est le nombre de mots dans la liste et m est la longueur d'un mot, alors le calcul du «numéro de groupe cyclique» pour tous les mots est le
O(n*m)
triO(n log n)
et le regroupementO(n)
.la source
Mathematica
Décidé de recommencer, maintenant que je comprends les règles du jeu (je pense).
Un dictionnaire de 10000 mots de "mots" uniques composés au hasard (minuscules uniquement) de longueur 3. De la même manière, d'autres dictionnaires ont été créés, composés de chaînes de longueur 4, 5, 6, 7 et 8.
g
prend la version actuelle du dictionnaire pour vérifier. Le mot du haut est joint à des variantes cycliques (le cas échéant). Le mot et ses correspondances sont ajoutés à la liste de sortieout
des mots traités. Les mots de sortie sont supprimés du dictionnaire.f
parcourt tous les mots du dictionnaire.Exemple 1 : mots réels
Exemple 2 : Mots artificiels. Dictionnaire de chaînes de longueur 3. Tout d'abord, le calendrier. Puis le nombre de mots du cycle.
Timings en fonction de la longueur des mots . 10000 mots dans chaque dictionnaire.
Je ne sais pas particulièrement comment interpréter les résultats en termes de O. En termes simples, le timing double à peu près du dictionnaire à trois caractères au dictionnaire à quatre caractères. Le timing augmente de façon presque négligeable de 4 à 8 caractères.
la source
Cela peut être fait en O (n) en évitant le temps quadratique. L'idée est de construire le cercle complet traversant deux fois la chaîne de base. Nous construisons donc "amazingamazin" comme la chaîne du cercle complet pour vérifier toutes les chaînes cycliques correspondant à "amazing".
Voici la solution Java:
la source
Je ne sais pas si c'est très efficace, mais c'est ma première fissure.
la source
Perl
Je ne suis pas sûr de comprendre le problème, mais cela correspond au moins à l'exemple @dude publié dans les commentaires. veuillez corriger mon analyse sûrement incorrecte.
pour chaque mot W dans les N mots donnés de la liste de chaînes, vous devez parcourir tous les caractères de W dans le pire des cas. je dois supposer que les opérations de hachage sont effectuées en temps constant.
la source