0Pricing
DSA Interview Prep · Lección

Búsqueda con comodines y expresiones regulares en un trie

Admite la coincidencia del comodín '.' ramificándose hacia todos los hijos en esa profundidad y resuelve el problema de la estructura de datos design-add-and-search-words.

Búsqueda con comodines y expresiones regulares en un trie es una lección gratuita de DSA Interview Prep en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de DSA Interview Prep, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de DSA Interview Prep incluye 4 lecciones en total.

El problema de la búsqueda con comodines

La búsqueda estándar en un trie gestiona caracteres exactos. La búsqueda con comodines añade un carácter especial '.' que coincide con cualquier carácter individual. Al encontrar un '.' durante la búsqueda, en lugar de seguir un único hijo específico, debemos probar todos los hijos: se produce una ramificación. Esta es la idea central de LeetCode 211, «Design Add and Search Words Data Structure». Cada '.' multiplica las rutas de búsqueda por el número de hijos de ese nivel.

Búsqueda recursiva con comodines

Implemente la búsqueda con comodines mediante una función auxiliar recursiva de DFS. Para cada carácter del patrón: si es un carácter literal, siga el hijo específico (o devuelva False si falta); si es '.', haga una llamada recursiva para todos los hijos y devuelva True si alguna tiene éxito. Al final del patrón, devuelva node.is_end.

class TrieNode:
    def __init__(self):
        self.children = {}
        self.is_end = False

class WordDictionary:
    def __init__(self):
        self.root = TrieNode()
    
    def addWord(self, word):
        node = self.root
        for c in word:
            if c not in node.children:
                node.children[c] = TrieNode()
            node = node.children[c]
        node.is_end = True
    
    def search(self, word):
        def dfs(node, i):
            if i == len(word):
                return node.is_end
            c = word[i]
            if c == '.':
                return any(dfs(child, i+1) for child in node.children.values())
            if c not in node.children:
                return False
            return dfs(node.children[c], i+1)
        return dfs(self.root, 0)

wd = WordDictionary()
wd.addWord('bad')
wd.addWord('dad')
wd.addWord('mad')
print(wd.search('.ad'))  # True
print(wd.search('b..'))  # True
print(wd.search('pad'))  # False

Por qué usar any() para la ramificación

Cuando se encuentra un '.', llamamos a any(dfs(child, i+1) for child in node.children.values()). El generador any() utiliza evaluación de cortocircuito: se detiene en cuanto un hijo devuelve True. Esto evita exploraciones innecesarias. En el peor caso (un patrón compuesto únicamente por '.'), exploramos todas las rutas; la complejidad es O(26^k), donde k es el número de puntos, por lo que patrones como '....' resultan costosos en tries grandes.

Búsqueda iterativa con comodines y colas

Un enfoque iterativo utiliza una cola de pares (node, index). Comience con (root, 0). Para cada par, si index == len(word) y node.is_end, devuelva True. De lo contrario, procese el carácter actual: para '.', añada todos los hijos a la cola; para un carácter literal, añada únicamente el hijo coincidente. En esencia, se trata de un BFS sobre las rutas del trie.

from collections import deque

def search_iterative(root, word):
    queue = deque([(root, 0)])
    while queue:
        node, i = queue.popleft()
        if i == len(word):
            if node.is_end:
                return True
            continue
        c = word[i]
        if c == '.':
            for child in node.children.values():
                queue.append((child, i+1))
        elif c in node.children:
            queue.append((node.children[c], i+1))
    return False

print('Iterative BFS-based wildcard search')

Análisis de complejidad de la búsqueda con comodines

Para un patrón sin comodines, la búsqueda es O(m). Para un patrón con k comodines, el peor caso es O(26^k × m): es exponencial respecto al número de comodines. En la práctica, los comodines suelen ser poco frecuentes y el trie no suele ser profundo, por lo que el rendimiento es aceptable. En patrones compuestos completamente por comodines (por ejemplo, para encontrar todas las palabras de longitud k), la búsqueda degenera en un recorrido completo del trie.

Búsqueda con expresiones regulares más allá de los comodines de un carácter

Ampliar la búsqueda a expresiones regulares completas (por ejemplo, '*', que coincide con cero o más caracteres) requiere un tratamiento diferente. Un '*' puede coincidir con cualquier sufijo, por lo que, al encontrarlo, debemos probar todas las rutas del trie desde el nodo actual. La coincidencia de expresiones regulares reales en un trie es compleja y normalmente se reserva para construcciones NFA/DFA. En entrevistas, el patrón estándar son los comodines de un solo carácter ('.').

Coincidencia de patrones glob

La coincidencia de patrones glob con '?' (cualquier carácter individual) y '*' (cualquier secuencia, incluida la vacía) se puede implementar mediante DP. Si se implementa en un trie, '?' corresponde a una ramificación de un solo nivel (como '.') y '*' corresponde a un DFS de varios niveles. El enfoque combinado de DP es el siguiente: dp[i][j] = True si pattern[0..i] coincide con string[0..j]. Por lo general, el entrevistador especifica qué variante se debe implementar.

Aplicación práctica: enrutamiento de direcciones IP

Los tries con comodines se utilizan en las tablas de enrutamiento IP, donde '*' actúa como comodín de prefijo. Un router almacena prefijos de ruta como '192.168.*' y compara las direcciones entrantes. La coincidencia del prefijo más largo (gana la ruta más específica) se implementa recorriendo el trie hasta la mayor profundidad posible y utilizando la última coincidencia encontrada. Esta es una aplicación real de las operaciones de prefijo y comodines de los tries.

Optimización: podar ramas muertas

Cuando un nodo del trie no tiene hijos (es una hoja) y is_end = False, cualquier búsqueda que llegue a él devuelve False. Durante la búsqueda con comodines, omitir estos nodos sin salida antes de realizar la recursión permite evitar llamadas innecesarias. Mantener un word_count en cada nodo (el total de palabras del subárbol) permite omitir un subárbol completo si ninguna palabra puede coincidir con las restricciones de longitud restantes del patrón.

Clase WordDictionary completa, lista para entrevistas

Una clase WordDictionary limpia y lista para entrevistas que combina la inserción y la búsqueda con comodines de punto en una sola clase. Esta es la implementación exacta que se espera para LeetCode 211. La búsqueda recursiva con any() de cortocircuito es concisa y demuestra claramente la lógica de ramificación a los entrevistadores.

class WordDictionary:
    def __init__(self):
        self.root = {}
    
    def addWord(self, word):
        node = self.root
        for c in word:
            node = node.setdefault(c, {})
        node['#'] = True
    
    def search(self, word):
        def dfs(node, i):
            if i == len(word):
                return '#' in node
            if word[i] == '.':
                return any(dfs(v, i+1) for k, v in node.items() if k != '#')
            nxt = node.get(word[i])
            return dfs(nxt, i+1) if nxt is not None else False
        return dfs(self.root, 0)

wd = WordDictionary()
for w in ['at','and','an','add']:
    wd.addWord(w)
print(wd.search('a.'))   # True (at, an)
print(wd.search('.nd'))  # True (and)
print(wd.search('...'))  # True (and, add)
print(wd.search('x.'))   # False

Usar setdefault para un trie compacto

dict.setdefault(key, default) devuelve el valor de key si está presente; de lo contrario, inserta default y lo devuelve. Usar node.setdefault(c, {}) en la inserción elimina la comprobación if-else: crea el diccionario hijo si falta y lo devuelve en cualquier caso. Esto convierte la inserción en un recorrido de una sola línea: for c in word: node = node.setdefault(c, {}). Limpio y propio del estilo de Python.

Comprobación rápida

Ponga a prueba su comprensión de los conceptos de Data Structures & Algorithms — Coding Interview Prep de esta lección.

Resumen de la lección

En esta lección aprendió: el comodín '.' requiere ramificarse hacia todos los hijos en la posición correspondiente mediante un DFS recursivo, usar any() con un generador proporciona evaluación de cortocircuito para terminar antes, y setdefault permite realizar una inserción compacta del trie en una sola línea. A continuación combinaremos tries y backtracking para resolver Word Search II: encontrar varias palabras simultáneamente en un tablero 2D.

Preguntas frecuentes

¿La lección «Búsqueda con comodines y expresiones regulares en un trie» es gratis?

Sí — el texto completo de «Búsqueda con comodines y expresiones regulares en un trie» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de DSA Interview Prep, actualiza a CoddyKit PRO. El curso de DSA Interview Prep incluye 4 lecciones en total.

¿Qué aprenderé en «Búsqueda con comodines y expresiones regulares en un trie»?

Admite la coincidencia del comodín '.' ramificándose hacia todos los hijos en esa profundidad y resuelve el problema de la estructura de datos design-add-and-search-words. Practicas DSA Interview Prep con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar DSA Interview Prep?

No se requiere experiencia previa. DSA Interview Prep en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «Búsqueda con comodines y expresiones regulares en un trie»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de DSA Interview Prep?

Sí. Cada lección de DSA Interview Prep incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Clase TrieNode: inserción y búsqueda
  2. Búsqueda por prefijo y Starts-With
  3. Búsqueda con comodines y expresiones regulares en un trie
  4. Word Search II: trie y retroceso en una cuadrícula
← Volver a DSA Interview Prep