Saltar a contenido

Autómatas finitos para no creyentes

6 minutos de lectura · 19 febrero 2026

Los autómatas finitos suelen aparecer en la carrera, asustar, y desaparecer. Quedan en la memoria como un ejercicio académico sin uso práctico fuera de un compilador.

El problema no es que los autómatas sean inútiles. El problema es que ya los usas a diario y no lo sabes.

Cada regex que escribes es un autómata. Cada parser de protocolo. Cada validador de input. La idea de "estoy en un estado, leo un símbolo, transiciono" describe la mitad del código que escribimos.

La intuición sin formalismo

Un autómata finito es:

  • Un conjunto pequeño de estados (sí / no / esperando / leyendo).
  • Un alfabeto de símbolos que recibe uno a uno.
  • Una tabla de transiciones que dice: "si estoy en A y leo x, paso a B".
  • Uno o más estados de aceptación que significan "OK".

No hay memoria. No puedes contar. Solo dónde estás y qué leíste.

Esa restricción suena enorme. Lo es. Pero lo que sí cabe en ese cajón es sorprendente.

Tres ejemplos cotidianos

1. Validar contraseña

inicio --letra-->  visto_letra
inicio --digito--> visto_digito
visto_letra --digito--> ok
visto_digito --letra--> ok
ok --*--> ok

"Empieza con letra o dígito y antes de acabar tiene de los dos". Si llegas a ok antes de fin de cadena, la contraseña es válida. Esto es un autómata de cuatro estados que cabe en una función de quince líneas.

2. Parser de URL simple

inicio --letra--> esquema
esquema --letra--> esquema
esquema --:--> dos_puntos
dos_puntos --/--> slash1
slash1 --/--> slash2
slash2 --*--> host
host --/--> path

Te das cuenta de que estás escribiendo el flujo cada vez que parseas un protocolo. Lo que en libros se llama "tabla de transición" es lo que en tu código serían anidados if y match.

3. Detector de palabra clave en un stream

¿Cómo detectas la cadena ERROR en un log de bytes que llega por chunks? Si lo haces con substring, fallas en los bordes de chunk.

La forma robusta: autómata de seis estados (_, E, ER, ERR, ERRO, ERROR). En cualquier momento sabes "cuánto llevo de la palabra". Cuando un byte rompe la secuencia, retrocedes al estado correcto. Esto es Knuth-Morris-Pratt desnudo y es exactamente un DFA.

El truco mental que da poder

Cuando te pierdes en un trozo de código con flags y banderas:

if buscando_inicio and not encontrado:
    if c == '<':
        buscando_inicio = False
        if c2 == '/':
            cerrando = True
        ...

Para. Dibuja un autómata. Quince segundos en un papel y la maraña se vuelve un diagrama de cuatro burbujas y cinco flechas. El código que escribes después es la implementación literal del diagrama.

estado = "inicio"
for c in stream:
    match (estado, c):
        case ("inicio", "<"):  estado = "abierto"
        case ("abierto", "/"): estado = "cerrando"
        case ("abierto", _):   estado = "abriendo"
        case ("cerrando", ">"): emitir_cierre(); estado = "inicio"
        ...

Lo bonito: el match es el autómata. Los case son las flechas. Si añades un estado, añades dos casos. Sin banderas escondidas.

Por qué te enseñaron mal

El bloque académico empieza por la definición formal (⟨Q, Σ, δ, q₀, F⟩), prueba teoremas sobre lenguajes regulares, y solo en el último capítulo aparece "y esto se usa para regex".

Si lo empiezas por el final —"toma este código asqueroso, lo voy a rescribir como autómata"— el formalismo cae solo y con sentido. El orden importa.


Próxima entrada

El siguiente paso natural es el autómata con pila, que mete una pila y de pronto puede contar paréntesis. Y de ahí, el mundo entero de los parsers. En la próxima.

¿Comentarios o correcciones? info@encodigo.es.