de prefijo/sufijo árbol son generalmente la norma, mejor y más prudente solución para este tipo de cosas en mi opinión. No puedes equivocarte con ellos.
Pero aquí hay una idea diferente, que recurre a Bloom filters. Probablemente sepas qué son, pero por las dudas (y para otras personas que lean esta respuesta): los filtros Bloom son vectores de bits muy pequeños y muy compactos que se aproximan a la inclusión del conjunto. Si usted tiene un conjunto S y un filtro Bloom para ese conjunto B (S), entonces
x ∈ S ⇒ x ∈ B(S)
pero el movimiento alternativo que es falso. Esto es lo que es probabilístico sobre la estructura: existe una probabilidad (quantifiable) de que el filtro Bloom devuelva un falso positivo. Pero aproximar la inclusión con el filtro Bloom es salvajemente más rápido que probarlo exactamente en el conjunto.
(Un caso sencillo utilizar: en muchas aplicaciones, se utiliza el filtro Bloom, así, como un filtro Comprobación de caché es caro, porque hay que hacer un acceso al disco duro, por lo que programas como. Squid primero verificará un pequeño filtro Bloom en la memoria, y si el filtro Bloom arroja un resultado positivo, Squid revisará el caché. Si fue falso positivo, está bien, porque Squid lo descubrirá cuando visite el caché. --- pero la ventaja es que el filtro Bloom habrá evitado que Squid tenga que verificar la memoria caché para un montón de solicitudes donde habría sido inútil.)
Los filtros Bloom se usaron con cierto éxito en la cadena buscar. Aquí hay un boceto (puedo recordar algunos de los detalles incorrectos) de esta aplicación. Un archivo de texto es una secuencia de N líneas. Está buscando una palabra compuesta de M letras (y ninguna palabra se puede extender entre dos líneas). Una fase de preprocesamiento generará un filtro ONE Bloom para cada línea, agregando cada subsecuencia de la línea al filtro Bloom; por ejemplo, para esta línea
Touching this dreaded sight, twice seene of vs,
Y el filtro Bloom correspondiente será creado con "T", "A", "Tou" ... "o", "ou", ... "vs, "," s "," s ",", ". (Es posible que tenga esta parte incorrecta. O tal vez desee optimizar.)
Luego, cuando busque la subpalabra de tamaño M, simplemente haga una comprobación muy rápida de cada uno de los filtros Bloom, y cuando haya un golpe, examina la línea de cerca con el algoritmo KMP, por ejemplo. En la práctica, si sintoniza bien sus filtros Bloom, la compensación es notable. La búsqueda es increíblemente rápida porque eliminas todas las líneas inútiles.
Creo que a partir de este concepto podría derivar un esquema útil para su situación. En este momento, veo dos evidente adaptación:
o bien cortar su conjunto de datos en muchos bloques de tamaño K (cada uno con su filtro Bloom, como las líneas en el ejemplo anterior);
o utilice una especie de dicotomía en la que divide el conjunto en dos subconjuntos, cada uno con un filtro Bloom, luego cada subconjunto se divide en dos subconjuntos secundarios con su propio filtro Bloom, etc. (si va a agregue todas las subcadenas según lo sugerido con el método que describí, esta segunda idea sería un poco prohibitiva, excepto que no tiene que agregar todas las subcadenas, solo las subcadenas que varían del 1 al 10).
Ambas ideas se pueden combinar de forma ingeniosa para crear esquemas de varias capas.
Depende de la naturaleza de los datos. ¿Podrías ordenarlo, indexarlo, ...? (es posible que desee buscar en tablas de arcoíris, ya que para eso generalmente busca una cadena de 10 bytes en 10 mil millones de bytes) – mvds
Por cierto, la gran O a la que hace referencia no tiene en cuenta que los 10 mil millones de bytes pueden no caber en la memoria ¿Cuánto tienes de eso? Disco i/o es * realmente * lento en comparación con ram. – mvds
Y esta cadena de búsqueda de 10 bytes, ¿es aleatoria o hay un rango limitado de cadenas de búsqueda? realmente necesitas compartir algunos más detalles. – mvds