Regex e autômatos
Expressões regulares parecem magia para iniciantes, mas têm uma base matemática sólida: toda regex compila para um NFA (autômato finito não-determinístico), que por sua vez compila para um DFA. Entender essa cadeia explica tanto o poder quanto as limitações das regex.
Regex = linguagem para descrever linguagens
Uma expressão regular descreve um conjunto de strings — a linguagem que ela
reconhece. Por exemplo, (a|b)*abb descreve todas as strings sobre {a, b} que
terminam com "abb": "abb", "aabb", "babb", "aaabb", ...
O teorema de Kleene (1956) prova que as linguagens descritas por expressões regulares são
exatamente as linguagens reconhecidas por DFAs — as linguagens regulares.
Quando você escreve re.compile(r"\\d+"), o motor compila isso para um DFA
(via NFA intermediário) e o executa contra a entrada.
DFA para o padrão (a|b)*abb
Digite uma string com letras 'a' e 'b' e avance passo a passo. O DFA tem 4 estados; q3 (duplo círculo) é o único aceitador — a string deve terminar aqui.
Regex em Python
# Expressões regulares em Python — sintaxe e operações import re # Metacaracteres fundamentais: # . qualquer caractere (exceto \n por padrão) # * zero ou mais do anterior # + um ou mais do anterior # ? zero ou um do anterior # | alternância (ou) # () grupo # [] classe de caracteres # ^$ início e fim da string # Exemplos: re.match(r"(a|b)*abb", "aabb") # match — termina em "abb" re.match(r"\d+", "42px") # match "42" re.fullmatch(r"[A-Za-z_]\w*", "nome_1") # identificador re.findall(r"\b\w+\b", "olá mundo") # ['olá', 'mundo'] # Grupos de captura: m = re.match(r"(\d{4})-(\d{2})-(\d{2})", "2026-06-14") m.group(1) # '2026' m.group(2) # '06' m.group(3) # '14'
Construção de Thompson: de regex para NFA
# Compilação de regex para NFA (construção de Thompson) # Cada operação de regex produz um fragmento de NFA # Símbolo 'a': # →[q_ini] --a--> [q_fim] # Concatenação: r · s (r seguido de s) # NFA(r).fim → ε → NFA(s).ini # Alternância: r | s # novo_ini → ε → NFA(r).ini # novo_ini → ε → NFA(s).ini # NFA(r).fim → ε → novo_fim # NFA(s).fim → ε → novo_fim # Fechamento de Kleene: r* # novo_ini → ε → NFA(r).ini # novo_ini → ε → novo_fim (aceita string vazia) # NFA(r).fim → ε → NFA(r).ini (repetição) # NFA(r).fim → ε → novo_fim # Após construir NFA → algoritmo de subconjuntos → DFA # re.compile() faz exatamente isso (em C, muito rápido)
re,
PCRE) usam backtracking com extensões (lookahead, backreferences) que vão além de
linguagens regulares — mas podem ter complexidade exponencial no pior caso (ReDoS).
Motores baseados em DFA puro (RE2, ripgrep) garantem O(n) no comprimento da entrada mas
não suportam backreferences. Ripgrep — o grep mais rápido — usa um motor DFA híbrido
escrito em Rust.
Construindo um motor de regex
Mini projeto: implemente um motor de regex simplificado que suporte apenas ., * e caracteres literais (sem grupos ou alternância). Use a abordagem de simulação direta de NFA: para cada caractere da entrada, compute o conjunto de estados alcançáveis por transições ε. Teste com padrões como "a*b", ".*c".
Projeto principal: estenda o motor para suportar |, () e +. Compile a regex para NFA usando a construção de Thompson (representação explícita como grafo). Execute o NFA com simulação de subconjunto. Verifique que o resultado é idêntico ao módulo re para 1000 strings aleatórias.
Desafio extra: implemente um detector de ReDoS: dado um padrão regex, analise se ele pode exibir backtracking exponencial (ambiguidade exponencial). Use a técnica de análise de "caminhos de estrela aninhadas" — se encontrar, reporte qual subcadeia pode causar o pior caso e sugira uma reescrita.
Teste sua intuição
Onde você encontra isso
ripgrep — busca ultrarrápida
ripgrep (rg) é a ferramenta de busca mais rápida em benchmarks reais. Internamente usa a crate regex do Rust, que compila padrões para DFAs hibridizados — lazy DFAs que constroem estados sob demanda e DFAs completos para padrões simples. Garante O(n) sem risco de ReDoS. É o motor de busca padrão do VS Code e do GitHub code search.
WAF — Web Application Firewall
Firewalls de aplicação web usam regex para detectar payloads maliciosos (SQL injection, XSS). Um WAF mal escrito com regex backtracking é vulnerável ao próprio ReDoS: um atacante envia uma string maliciosa que faz o motor de regex ficar em loop exponencial, causando DoS no firewall. CloudFlare sofreu um incidente desse tipo em 2019, derrubando serviços por 27 minutos.
Bioinformática — busca em genomas
Ferramentas como BLAST e HMMER buscam padrões em sequências de DNA e proteínas. As sequências são strings sobre alfabetos {A, C, G, T} ou os 20 aminoácidos. Modelos de Markov ocultos (HMMs) são generalizações probabilísticas de autômatos — cada estado emite um símbolo com uma certa probabilidade. Um perfil HMM de uma família proteica é essencialmente um autômato treinado.