Diccionario Principios y Aplicaciones árbol

En primer lugar, el concepto

Diccionario árbol, también conocido como trie, árbol Trie es un árbol, es una variante del árbol de hash. Las aplicaciones típicas para las estadísticas, ordena y guarda una gran cantidad de cadenas (cadenas, pero no limitado a), a menudo se utiliza para las estadísticas de frecuencia del sistema motor de búsqueda de texto, búsqueda de Lenovo. Sus ventajas son: el uso del prefijo común de la cadena para reducir el tiempo de consulta, lo que minimiza la comparación de cadenas innecesarias.

En segundo lugar, las características

  • No contiene nodo raíz carácter, cada nodo excepto el nodo raíz contiene sólo el carácter exterior;
  • Desde el nodo raíz a un nodo en el camino a través de la cadena de caracteres correspondiente conectado a dicho nodo;
  • Todos los caracteres de cada nodo contiene nodos hijos no son los mismos.

En tercer lugar, la operación común

Encontrar, insertar y borrar (poco frecuente).

En cuarto lugar, para lograr

El siguiente código, los implementos de código trie insertar y un método de acuerdo con el prefijo que coincida con todas las cadenas.

público  de clase Trie { 

    privada raíz TrieNode; 

    pública Trie () { 
        raíz = nueva TrieNode (); 
    } 

    Pública  nula inserción (String str) {
         si (str == nula || str.length () == 0 ) {
             retorno ; 
        } 
        Nodo TrieNode = raíz;
        Char [] AllChars = str.toCharArray ();
        para ( int i = 0; i <allChars.length; i ++ ) { 
            carácter Carácter = nuevoCarácter (AllChars [i]);
            si (! node.children.containsKey (carácter)) { 
                node.children.put (carácter, nueva TrieNode (carácter)); 
            } 
            Nodo = node.children.get (carácter); 
        } 
        Node.isEnd = verdadero ; 
    } 

    Pública List <String> matchPrefix (cadena de prefijo) { 
        Lista <String> resultado = nuevo ArrayList <String> ();
        si (prefijo == nula || prefix.length () == 0 ) {
             retorno  resultado;
        }
        Char [] AllChars = prefix.toCharArray (); 
        Nodo TrieNode = raíz;
        para ( int i = 0; i <allChars.length; i ++ ) { 
            Carácter carácter = nuevos caracteres (AllChars [i]);
            si (! node.children.containsKey (carácter)) {
                 retorno de resultado; 
            } Más { 
                nodo = node.children.get (carácter); 
            } 
        } 
        PreTraverse (nodo, prefijo, resultado); 
        retorno  resultado;
    } 

    privada  sin efecto preTraverse (nodo TrieNode, cadena de prefijo, List <String> resultado) {
         si (! Node.children.isEmpty ()) {
             a (Map.Entry <Carácter, TrieNode> entrada: node.children.entrySet ()) {
                 si (entry.getValue () iSend.) { 
                    result.add (prefijo + entry.getKey () toString ().); 
                } 
                PreTraverse (entry.getValue (), prefijo + entry.getKey () toString (), resultado.); 
            } 
        } 
    } 

    Privada  clase TrieNode { 

        privada Mapa <Carácter, TrieNode> niños; 

        privado boolean iSend; 

        privada de caracteres; 

        TrieNode () { 
            hijos = nuevo HashMap <Carácter, TrieNode> (); 
            iSend = false ; 
        } 

        TrieNode (de caracteres) { 
            hijos = nuevo HashMap <Carácter, TrieNode> (); 
            iSend = false ;
            este .character = carácter; 
        } 
    } 
}

 

Lo probamos por un trozo de código:

público  de clase MainApp { 

    pública  estática  vacío main (String [] argv) { 
        ArrayList <String> = STRs nueva nueva ArrayList <String> (); 
        strs.add ( "Me encanta aprender" ); 
        strs.add ( "Me encanta la escuela" ) ; 
        strs.add ( "me encanta aprender java" ); 
        strs.add ( "no me gusta mucho aprender" ); 
        strs.add ( "aprendizaje Xiao Ming amor" ); 
        strs.add ( "me encanta Python" ); 

        Trie Trie = nuevo nuevo Trie ();
         para (String S:STRs) { 
            trie.insert (s); 
        }
        Cadena de prefijo = "我爱" ; 
        Lista <String> res = trie.matchPrefix (prefijo); 
        System.out.println (res); 
    } 
}

Después de realizar la salida: [Python Me encanta, me encanta aprender, me encanta aprender y me gusta aprender JAVA]

V. Aplicación

Dada una lista de palabras, esta lista se codifica como un índice de la cadena S y una lista de índice A.

Por ejemplo, si la lista es [ "tiempo", "yo", "campana"], que puede expresarse como S = "tiempo de campana # #" y los índices = [0, 2, 5].

Para cada índice, podemos empezar por la lectura del índice de la cadena de la cadena S en la posición hasta el final "#", para restaurar nuestra lista previa de las palabras.

A continuación, la longitud mínima de la cadena para el éxito de una lista de palabras dada para la codificación es ¿cuánto?

Ejemplo:

Entrada: palabras = [ "tiempo", "yo", "campana"]
de salida: 10
Descripción: S = "tiempo de campana # # ", los índices = [0, 2, 5]

Por análisis, podemos ver, esta pregunta no es seguro que todas las otras palabras reservados palabra sufijo, el resultado final es la suma de una más la longitud de la palabra (como la necesidad de mantener la parte de atrás después de cada palabra codificada  # de símbolos). Debería ser obvio para utilizar una tabla de diccionario. Código es el siguiente:

clase de soluciones {
     pública  int minimumLengthEncoding (String [] palabras) { 
        Trie trie = nueva Trie (); 
        HashMap <TrieNode, Integer> nodos = nuevo HashMap <TrieNode, Integer> (); 
        
        para ( int k = 0; k <words.length; k ++ ) { 
            cadena s = palabras [k]; 
            TrieNode nodo = trie.insert (s);
            si (! nodo = nulo ) { 
                nodes.put (nodo, k);    
            } 
        } 
        Int res = 0 ;
        para (TrieNode n: nodes.keySet ()) {
             si (n.children.isEmpty ()) { 
                res . + = palabras [nodes.get (n)] Longitud () + 1 ; 
            } 
        } 
        Volver res; 
    } 
} 

Clase Trie { 
    raíz TrieNode; 
    Trie () { 
        raíz = nueva TrieNode (); 
    } 
    TrieNode inserto (str String) { 
        si (str == nula || str.length () == 0 ) {
             retorno  nulo ; 
        } 
        Nodo TrieNode = raíz;
        carbonizarse[] AllChars = str.toCharArray ();
        para ( int i = allChars.length-1; i> = 0; i-- ) { 
            carácter Carácter = nuevo de caracteres (AllChars [i]);
            si (! node.children.containsKey (carácter)) { 
                node.children.put (carácter, nueva TrieNode (carácter)); 
            } 
            Nodo = node.children.get (carácter); 
        } 
        Node.isEnd = verdadero ;
        volver nodo; 
    } 
} 

Clase TrieNode { 
    Mapa<Carácter, TrieNode> niños;
    boolean iSend; 
    De caracteres; 
    TrieNode () { 
        hijos = nuevo HashMap <Carácter, TrieNode> (); 
        iSend = false ; 
    } 
    TrieNode (de caracteres) { 
        hijos = nuevo HashMap <Carácter, TrieNode> (); 
        iSend = false ;
        este .character = carácter; 
    } 
}

Aquí las estadísticas con el fin de facilitar la cadena final, por lo que el código de la tabla diccionario proporcionó anteriormente en este artículo modifica ligeramente, pero la idea general es la misma.

Supongo que te gusta

Origin www.cnblogs.com/blackwatch1206/p/12596060.html
Recomendado
Clasificación