Skip to content
Clases

Lenguajes Formales

En Programación Competitiva, muchos problemas de strings (como validación de paréntesis o búsqueda de patrones) son en realidad problemas de Teoría de Lenguajes.

Un conjunto finito de símbolos.

  • Ejemplo: Σ={a,b,,z}\Sigma = \{a, b, \dots, z\}

Un conjunto de strings formadas con símbolos de Σ\Sigma.

  • Formalmente: LΣL \subseteq \Sigma^*

Sean L1L_1 y L2L_2 dos lenguajes:

  • Unión: L1L2L_1 \cup L_2 (Cadenas que están en uno u otro).
  • Concatenación: L1L2={xyxL1,yL2}L_1 L_2 = \{xy \mid x \in L_1, y \in L_2\}.
  • Cerradura de Kleene (LL^*): Repetir LL cero o más veces (incluye la cadena vacía ϵ\epsilon).
  • Cerradura Positiva (L+L^+): Repetir LL una o más veces.

Son una notación algebraica para definir lenguajes regulares (patrones).

Ejemplo: Definir un lenguaje para números (enteros o decimales, positivos o negativos).

  • Alfabeto: Dígitos D={0,,9}D = \{0, \dots, 9\}, signo {}\{-\}, punto {.}\{.\}.
  • Expresión: R=(ϵ)D+(.D+ϵ)R = (- \cup \epsilon) D^+ (. D^+ \cup \epsilon)
ParteSignificado
(ϵ)(- \cup \epsilon)Un guion opcional.
D+D^+Uno o más dígitos (parte entera).
(.D+ϵ)(. D^+ \cup \epsilon)Opcionalmente, un punto y más dígitos.

Una gramática define reglas para generar cadenas. Son la base de problemas como “Paréntesis Balanceados”.

Ejemplo: ¿Está bien formada (())()? Reglas recursivas para una cadena válida SS:

  1. SϵS \to \epsilon (Cadena vacía es válida).
  2. S(S)S \to (S) (Podemos rodear una válida con paréntesis).
  3. SSSS \to SS (Podemos concatenar dos válidas).

Un autómata es una máquina abstracta que lee una cadena y cambia de estado. Al final, decide si Acepta o Rechaza.

Queremos aceptar cadenas binarias con un número par de 1s.

  • Estados: EparE_{par} (Inicial, Aceptación), EimparE_{impar}.
  • Transiciones:
    • Si leo 0: Me quedo donde estoy.
    • Si leo 1: Cambio de estado (ParImparPar \leftrightarrow Impar).

Si la cadena termina en EparE_{par}, es válida.


La teoría de autómatas y hashing es la base de los algoritmos de búsqueda eficientes (más rápidos que el .find() básico que es O(NM)O(N \cdot M)).

  1. Rabin-Karp: Usa Rolling Hash (Prefix Sum de hashes) para comparar patrones en O(1)O(1).
  2. KMP (Knuth-Morris-Pratt): Construye un autómata (o arreglo de prefijos LPS) para no retroceder nunca en el texto. Complejidad O(N+M)O(N+M).