Cette question est une extension de Vérifier si les mots sont des isomorphes et en copie la première partie pour donner la définition d'un isomorphe.
Deux mots sont isomorphes s'ils ont le même schéma de répétitions de lettres. Par exemple, les deux ESTATE
et DUELED
ont un motifabcdca
ESTATE
DUELED
abcdca
parce que les lettres 1 et 6 sont les mêmes, les lettres 3 et 5 sont les mêmes, et rien de plus. Cela signifie également que les mots sont liés par un chiffre de substitution, ici avec la correspondance E <-> D, S <-> U, T <-> E, A <-> L
.
Étant donné deux chaînes X et Y, avec X ne dépassant pas Y, la tâche consiste à déterminer s'il existe une sous-chaîne de Y qui est un isomorphe avec X.
Entrée: Deux chaînes de lettres non vides de a..zA..Z dont une chaîne par ligne. Cela proviendra de l'entrée standard.
Sortie Une sous-chaîne de la deuxième chaîne qui est un isomorphe avec la première chaîne, si une telle chose existe. Sinon, affichez "Non!".
Règles Votre code doit s'exécuter en temps linéaire sur la longueur totale de l'entrée.
Score Votre score est le nombre d'octets dans votre code. Le moins d'octets gagne.
Exemple d'entrée et de sortie
adca
ddaddabdaabbcc
dabd
Pointe
Il existe au moins une solution temporelle pas si compliquée, pratiquement rapide et linéaire à ce problème.
Réponses:
Python 2,
338326323321310306297293290289280279266264259237230229226223222220219217 (260238231228225223221220218 avec 0 statut de sortie)L'algorithme est une variante de KMP, utilisant un test basé sur un index pour la correspondance des caractères. L'idée de base est que si nous obtenons un décalage à la position,
X[i]
nous pouvons retomber à l'endroit suivant possible pour une correspondance selon le suffixe le plus longX[:i]
qui est isomorphe à un préfixe deX
.De gauche à droite, nous attribuons à chaque caractère un index égal à la distance à l'occurrence précédente la plus récente de ce caractère, ou s'il n'y a pas d'occurrence précédente, nous prenons la longueur du préfixe de chaîne actuel. Par exemple:
Pour tester si deux caractères correspondent, nous comparons les indices en ajustant de manière appropriée les indices supérieurs à la longueur de la (sous-) chaîne actuelle.
L'algorithme KMP devient un peu simplifié car nous ne pouvons pas obtenir une différence sur le premier caractère.
Ce programme génère la première correspondance s'il en existe une. J'utilise une erreur d'exécution pour quitter en cas de correspondance, mais le code peut être facilement modifié pour quitter proprement au prix de quelques octets.
Remarque: Pour le calcul des indices, nous pouvons utiliser
str.rfind
(contrairement à mon approche précédente en utilisant un dictionnaire) et avoir toujours une complexité linéaire, en supposant questr.rfind
commence la recherche depuis la fin (ce qui semble être le seul choix d'implémentation sain) - pour chaque caractère de l'alphabet , nous n'avons jamais à parcourir deux fois la même partie de la chaîne, il y a donc une limite supérieure de comparaison (taille de l'alphabet) * (taille de la chaîne).Étant donné que le code est devenu assez obscur au cours du golf, voici une solution antérieure (293 octets) qui est un peu plus facile à lire:
La
e
fonction teste l'équivalence des caractères. L'exec
instruction assigne des indices et effectue quelques initialisations variables. La première boucle traiteX
les valeurs de repli et la seconde boucle effectue la recherche de chaîne.Mise à jour: voici une version qui se termine proprement, au prix d'un octet:
la source
r=raw_input
vs r =input
enregistre 4 octets et les parens sur l'impression ne coûtent que 3.exec
.Python 3, 401 octets
C'est encore en grande partie non golfé, mais je pense que cela devrait fonctionner. L'algorithme de base est KMP , plus un facteur supplémentaire qui est factoriel dans la taille de l'alphabet (ce qui est bien, car l'alphabet est constant). En d'autres termes, il s'agit / devrait être un algorithme linéaire complètement impraticable.
Voici quelques annotations pour aider à l'analyse:
Pour les tests, vous pouvez remplacer
s
par un alphabet plus petit questring.ascii_letters
.la source
APL (Dyalog) , 32 octets
Il s'agit d'une fonction d'infixe, prenant X comme argument de gauche et Y comme argument de droite.
Essayez-le en ligne!
{
…}
Lambda anonyme où⍺
et⍵
représentent les arguments (X et Y)⍳⍨⍺
ɩ selfie ndex de X ( ɩ ndices de la première occurrence des éléments de X dans X)⊂
joindre afin que nous puissions rechercher ce motif entier(
...)⍳
ɩ ndex de la première occurrence de ce dans ...≢⍺
décompte (longueur) de X⍵,/⍨
toutes les sous-chaînes de cette taille de Y (lit. réduction de concaténation de celles-ci, mais c'est un no-op)s←
stocker danss
(pour s ubstrings)⍳⍨¨
ɩ selfie ndex de chacun de ceuxnous avons maintenant l'index du premier motif, ou 1 + le nombre de motifs si aucune correspondance n'a été trouvée
(
…)⊃⍨
Utilisez cet indice pour choisir parmi…⊂'No!'
la chaîne incluse (pour qu'elle fonctionne comme un seul élément)s,
ajouté avecs
la source