Esta pregunta es una extensión de Verificar si las palabras son isomorfos y copia la primera parte para dar la definición de un isomorfo.
Dos palabras son isomorfos si tienen el mismo patrón de repeticiones de letras. Por ejemplo, ambos ESTATE
y DUELED
tienen patrónabcdca
ESTATE
DUELED
abcdca
Como las letras 1 y 6 son iguales, las letras 3 y 5 son iguales, y nada más. Esto también significa que las palabras están relacionadas por un cifrado de sustitución, aquí con la coincidencia E <-> D, S <-> U, T <-> E, A <-> L
.
Dadas dos cadenas X e Y, con X no más largo que Y, la tarea es determinar si hay una subcadena de Y que es un isomorfo con X.
Entrada: Dos cadenas de letras no vacías de a..zA..Z que una cadena por línea. Esto vendrá de la entrada estándar.
Salida Una subcadena de la segunda cadena que es un isomorfo con la primera cadena, si existe tal cosa. De lo contrario, salga "¡No!".
Reglas Su código debe ejecutarse en tiempo lineal en la longitud total de la entrada.
Puntaje Su puntaje es el número de bytes en su código. Pocos bytes ganan.
Ejemplo de entrada y salida
adca
ddaddabdaabbcc
dabd
Propina
Hay al menos una solución de tiempo no tan complicada, prácticamente rápida y lineal para este problema.
Respuestas:
Python 2,
338326323321310306297293290289280279266264259237230229226223222220219217 (260238231228225223221220218 con 0 estado de salida)El algoritmo es una variación de KMP, utilizando una prueba basada en índices para la coincidencia de caracteres. La idea básica es que si obtenemos un desajuste en la posición,
X[i]
entonces podemos recurrir al siguiente lugar posible para una coincidencia de acuerdo con el sufijo más largoX[:i]
que sea isomorfo a un prefijo deX
.Trabajando de izquierda a derecha, asignamos a cada carácter un índice igual a la distancia a la ocurrencia anterior más reciente de ese carácter, o si no hay una ocurrencia previa, tomamos la longitud del prefijo de cadena actual. Por ejemplo:
Para probar si dos caracteres coinciden, comparamos los índices, ajustándolos apropiadamente para los índices que son mayores que la longitud de la (sub) cadena actual.
El algoritmo KMP se simplifica un poco, ya que no podemos obtener una falta de coincidencia en el primer carácter.
Este programa genera la primera coincidencia si existe. Utilizo un error de tiempo de ejecución para salir en caso de una coincidencia, pero el código se puede modificar fácilmente para salir limpiamente a costa de algunos bytes.
Nota: Para los índices de computación, podemos usar
str.rfind
(a diferencia de mi enfoque anterior usando un diccionario) y aún tener una complejidad lineal, suponiendo questr.rfind
comience a buscar desde el final (que parece la única opción de implementación sensata), para cada carácter del alfabeto , nunca tenemos que atravesar la misma parte de la cadena dos veces, por lo que hay un límite superior de (tamaño del alfabeto) * (tamaño de la cadena) comparaciones.Dado que el código se ofuscó bastante en el curso de golf, aquí hay una solución anterior (293 bytes) que es un poco más fácil de leer:
La
e
función prueba la equivalencia de caracteres. Laexec
declaración asigna índices y realiza algunas inicializaciones variables. El primer bucle procesa losX
valores de retroceso y el segundo bucle realiza la búsqueda de cadenas.Actualización: Aquí hay una versión que sale limpiamente, a costa de un byte:
fuente
r=raw_input
vs. r =input
ahorra 4 bytes y los parens en impresión solo cuestan 3.exec
.Python 3, 401 bytes
Esto sigue siendo en su mayoría sin golf, pero creo que debería funcionar. El algoritmo central es KMP , más un factor adicional que es factorial en el tamaño del alfabeto (lo cual está bien, ya que el alfabeto es constante). En otras palabras, este es / debería ser un algoritmo lineal completamente poco práctico.
Aquí hay algunas anotaciones para ayudar con el análisis:
Para las pruebas, puede reemplazar
s
con un alfabeto más pequeño questring.ascii_letters
.fuente
APL (Dyalog) , 32 bytes
Esta es una función infija, tomando X como argumento izquierdo e Y como argumento derecho.
Pruébalo en línea!
{
…}
Lambda anónima donde⍺
y⍵
representan los argumentos (X e Y)⍳⍨⍺
ɩ ndex selfie de X ( Ɩ ndices de la primera aparición de elementos de X en X)⊂
adjuntar para que podamos buscar todo ese patrón(
...)⍳
ɩ índice de la primera aparición de eso en ...≢⍺
cuenta (longitud) de X⍵,/⍨
todas las subcadenas de ese tamaño de Y (literalmente, reducción de concatenación de esas, pero eso es un no-op)s←
almacenar ens
(para s ubstrings)⍳⍨¨
ɩ ndex selfie de cada uno de aquellosahora tenemos el índice del primer patrón, o 1 + el número de patrones si no se encontró coincidencia
(
...)⊃⍨
usa ese índice para elegir ...⊂'No!'
la cadena incluida (para que funcione como un solo elemento)s,
antepuesto cons
fuente