2012-03-27 25 views
5

Tengo un gran conjunto de direcciones URL y quiero implementar una autocompletación. No me gusta la complejidad del enfoque ingenuo, ya que es lineal con el tamaño del conjunto:¿Cómo crear un índice de prefijo simple en Java?

for(String url: urls) if(url.startsWith(input) {doSomething();} 

Ahora sé que en un hash Conjunto, la función "contiene()" obras en "O (1) "pero no hay" containsPrefix() ". ¿Hay una manera simple sin usar una gran biblioteca como Lucene o codificarla yo mismo? No tendría problemas para hacerlo, pero parece excesivo para un problema tan simple, así que quiero saber si existe una solución simple existente :-)

De mis clases de informática recuerdo un árbol que consta de fragmentos de cuerdas pero Olvidé cómo se llamaba. Funcionó así:

[car, care, carrot,carrotville]-> 

car 
| 
-/ 
-e 
-rrot 
    | 
    ----ville 

P.S .: Como llamar en los métodos que devuelve todas las cadenas que una cadena es el prefijo de? Al igual que si a es el prefijo de b, ¿qué es b a a?

+0

¿Qué quieres hacer? ¿Agregar automáticamente un texto al comienzo de cada cadena? –

+0

Quiero saber de qué cadenas es un prefijo mi cadena, así que puedo darles como sugerencias de autocompletado. –

Respuesta

2

Si usted necesita encontrar de manera eficiente prefijos de cadenas, utilice un Trie, una estructura de datos diseñada precisamente para ese propósito:

un trie, o árbol de prefijo, es una estructura de datos de árbol ordenado que se utiliza para almacenar una matriz asociativa donde las claves son generalmente cadenas. A diferencia de un árbol de búsqueda binario, ningún nodo en el árbol almacena la clave asociada con ese nodo; en cambio, su posición en el árbol define la clave con la que está asociado. Todos los descendientes de un nodo tienen un prefijo común de la cadena asociada con ese nodo, y la raíz se asocia con la cadena vacía

dos enlaces con sampleimplementations. Hace

+1

¡Perfecto! Utilicé el de https://forums.oracle.com/forums/thread.jspa?messageID=8787521 y funcionó en el primer intento. –

1

Hace tiempo puse una sencilla aplicación Trie aquí:

http://code.google.com/p/triebag/source/browse/trunk/src/triebag/tries/SimpleTrie.java

Sin embargo esto no es un trie compacta, por lo que crea un nodo por carácter, creando una compacta es un poco más complicado.

+0

¡Esto es genial! No me importa si es un nodo por personaje, pero dejaré la pregunta abierta solo en caso de que alguien tenga uno con múltiples. –

+0

Np, la versión compacta usa aproximadamente% 50 menos nodos (al menos para las palabras en turco en un diccionario) Este es el código de prueba, para que pueda verlo en acción, espero que no haya errores :) http://code.google.com/p/triebag/source/browse/trunk/test/triebag/tries/SimpleTrieTest.java – mdakin

+0

Probé tu SimpleTrie, pero parece que no funciona para mí. Primero, el constructor no era público y, después de cambiarlo, la siguiente prueba no arrojó nada: 'SimpleTrie trie = new SimpleTrie <>(); \t \t trie.add ("x", "x"); \t \t trie.add ("xy", "xy"); \t \t Iterator it = trie.getItemsWithPrefix ("x"); \t \t while (it.hasNext()) System.out.println (it.next()); ' –

0

java.util.regex.Pattern aplicación con la expresión regular puede manejar de manera eficiente prefijos:

StringBuilder buffer = new StringBuilder(); 
for (String prefix : prefixes) { 
    if (buffer.length() > 0) 
     buffer.append("|"); 
    buffer.append(prefix); 
} 
Pattern prefixPattern = Pattern.compile("^(" + buffer + ")"); 

puede probar todos los prefijos:

boolean containsPrefix = prefixPattern.matcher(stringToTest).find(); 

Nota: para simplificar, las cadenas de prefijos no se escapan. Caracteres Regexp [,], \, *,?, $, ^, (,), {,} Y | debe estar precedido por \.

Cuestiones relacionadas