2010-01-06 17 views
5

Gente Hellow Stack Overflow. Me gustaría recibir algunas sugerencias sobre el siguiente problema. Estoy usando Java.Subcadenas a juego de un diccionario a otra cadena: ¿sugerencias?

Tengo una matriz n. ° 1 con varias cadenas. Por ejemplo, dos de las cadenas podrían ser: "Una manzana cayó sobre la cabeza de Newton" y "Las manzanas crecen en los árboles".

Por otro lado, tengo otro array # 2 con términos como (Fruits => Apple, Orange, Peach; Items => Pen, Book; ...). Yo llamaría a esta matriz mi "diccionario".

Al comparar elementos de una matriz a la otra, necesito ver en qué "categoría" caen los elementos del # 1 de # 2. P.ej. Ambos del # 1 caerían bajo "Fruits".

Mi consideración más importante es la velocidad. Necesito hacer esas operaciones rápido. Una estructura que permita la recuperación de tiempo constante sería buena.

Consideré un Hashset con el método contains(), pero no permite subcadenas. También he intentado correr como expresiones regulares (manzana | naranja | melocotón | ... etc) con la caja de la bandera insensible, pero leí que no va a ser rápido cuando los términos aumentan en número (mínimo 200 es de esperar). Finalmente, busqué y estoy considerando usar una ArrayList con indexOf() pero no sé sobre su rendimiento. También necesito saber cuál de los términos realmente coincide, por lo que en este caso, sería "Apple".

Proporcione sus opiniones, ideas y sugerencias sobre este problema.

Vi el algoritmo Aho-Corasick, pero es muy probable que las palabras clave/términos cambien con frecuencia. Entonces no creo que pueda usar eso. Oh, no soy un experto en minería de textos y matemática, así que por favor elabore conceptos complejos.

¡Gracias, gente de Stack Overflow, por su tiempo! :)

+0

He comprobado el árbol de sufijos. Parece similar a la estructura Trie que utiliza Aho-Corasick algo. Mi preocupación es que tengo muchas categorías diferentes y muchos términos por categoría. Construir un árbol para cada categoría me parece ineficiente. Gracias Matt! –

+0

En realidad, no creo que necesite construir un árbol para cada categoría. Debería poder insertar varias cadenas en un solo árbol de sufijos y agregar una referencia a un objeto de categoría en el punto de terminación en el árbol de cada cadena válida. – MattK

+0

¡Esa idea es interesante! Pero no entiendo la parte "agregar referencia a un objeto de categoría" de su respuesta. ¿Cómo puedo hacer eso? –

Respuesta

2

¿Funcionaría un suffix tree o una estructura de datos similar para su aplicación? Ofrece O (m) cadena de búsqueda, donde m es la longitud de la cadena de búsqueda, después de una O (n) - o mejor con un poco de engaño - configuración inicial, y, con un poco de esfuerzo extra, puede asociar datos arbitrarios, como una referencia a una categoría, con palabras completas en su diccionario. Si no desea codificarlo usted mismo, creo que la biblioteca BioJava incluye una implementación.

También puede agregar cadenas a un árbol de sufijo después de la configuración inicial, aunque el costo seguirá siendo O (n). Probablemente no sea un gran problema si agrega palabras cortas.

+0

Tenga en cuenta que los árboles de sufijo son estructuras * lineales * (en espacio y tiempo). – ariels

+0

Tienes razón, eso me enseñará a responder preguntas a primera hora de la mañana. Por supuesto, la búsqueda es lineal en la longitud de la cadena de búsqueda, no la longitud de las cadenas contenidas en el árbol, que sigue siendo bastante eficiente. De todos modos, editó la respuesta para reflejar eso. – MattK

+0

Es posible que desee considerar el uso de Knuth-Morris-Pratt con el Trie, pero eso puede darle o no un aumento de velocidad (y si le puede importar o no). –

3

Si utiliza un multimapa de Google Collections, tienen una función para invertir el mapa (para que pueda comenzar con un mapa como {"Fruits" => [Apple]}, y producir un mapa con {"Apple" => ["Fruits"]}. Así que puedes buscar la palabra y encontrar una lista de categorías para ella, en una llamada al mapa.

Esperaría que quisiera dividir las cadenas y buscar el palabras en el mapa de a una por vez, de modo que pueda hacer derivaciones (ajuste para diferentes terminaciones de palabras) y filtrado de palabras prohibidas. Usar el mapa debería tener buenos tiempos de búsqueda, además es fácil de probar.

+0

Stemming ... Ahora que es algo interesante y que me he perdido. Si puedo contener (¿se lo llama así?) El título "Las manzanas crecen en los árboles" a "Manzana crecer en el árbol" y tokenizar eso, ya no necesito la coincidencia de subcadenas. El método contains() de Hashset me daría lo que necesito. Gracias Nathan Hughes. : D +1 para la punta de tallo! –

0

Si tiene solo 200 términos para buscar, las expresiones regulares podrían funcionar para usted. Por supuesto, la expresión egular es grande, pero si la compila una vez y solo utiliza este Patrón compilado, el tiempo de búsqueda es probablemente lineal en la longitud combinada de todas las cadenas en el arreglo # 1 y no veo cómo puede esperar ser mejor que eso .

Así que el algoritmo sería: concatenar las palabras de la matriz # 2 que desea buscar en la expresión regular, compilarla, y luego encontrar las coincidencias en la matriz # 1.

(Las expresiones regulares se compilan en una máquina de estados, es decir, en cada carácter de la cadena solo hace una búsqueda de tablas para el siguiente estado. Si la expresión regular es complicada, puede tener retroceso que aumente el tiempo, pero la expresión regular tiene una estructura muy simple.)

+0

Mi expresión regular es simple. Solo (manzana | naranjas | melocotón | ... etc.) para todas las palabras clave y una expresión regular por categoría. Aunque tenía dudas sobre su rendimiento. Compilé el patrón para volver a usarlo. –

+0

No entiendo completamente lo que quieres hacer. Pero si quieres buscar en todas las cadenas de la matriz n. ° 1 cualquier cosa que ocurra en la matriz n. ° 2, probablemente solo haga UNA expresión regular gigante con todo lo que ocurra allí, y buscaré eso. De lo contrario, tiene tantas búsquedas como categorías. Todo lo que he encontrado buscaría en un HashMap que correlaciona las palabras con sus categorías. Para ver si esto es factible, puede concatenar tantas palabras aleatorias como pueda obtener en una expresión regular gigante y verificar el tiempo de las búsquedas. –

Cuestiones relacionadas