Si sus problemas de memoria se encuentran en la creación del árbol de sufijos, ¿está seguro de que necesita uno? Se podía encontrar todos los partidos en una sola cadena como esta:
word=get_string(4**12)+"$"
def matcher(word, match_string):
positions = [-1]
while 1:
positions.append(word.find(match_string, positions[-1] + 1))
if positions[-1] == -1:
return positions[1:-1]
print matcher(word,'AAAAAAAAAAAA')
[13331731, 13331732, 13331733]
print matcher('AACTATAAATTTACCA','AT')
[4, 8]
Mi máquina es bastante viejo, y esto llevó 30 segundos para correr, con 4^12 cuerdas. Usé un objetivo de 12 dígitos, por lo que habría algunas coincidencias. Además, esta solución encontrará resultados superpuestos, en caso de haberlos.
Here es un módulo árbol de sufijos puede probar, como esto:
import suffixtree
stree = suffixtree.SuffixTree(word)
print stree.find_substring("AAAAAAAAAAAA")
Unfortunetly, mi máquina es demasiado lento para probar esto correctamente con cadenas largas. Pero, presumiblemente, una vez que se construya el sufijoxtirector, las búsquedas serán muy rápidas, por lo que para grandes cantidades de búsquedas debería ser una buena decisión. Además, find_substring
solo devuelve la primera coincidencia (no sé si esto es un problema, estoy seguro de que podrías adaptarlo fácilmente).
Actualización: dividir la cadena en sufijo árboles más pequeños, evitando así problemas de memoria
Así que si usted necesita para hacer 10 millones de búsquedas en 4^12 cadena de longitud, que claramente no quieren esperar a 9,5 años (búsqueda simple estándar, primero sugerí, en mi máquina lenta ...). Sin embargo, aún podemos usar árboles de sufijos (por lo tanto, es mucho más rápido), Y evitar los problemas de memoria. Divide la secuencia grande en fragmentos manejables (que sabemos que la memoria de la máquina puede manejar) y convierte un fragmento en un árbol de sufijos, búscalo 10 millones de veces, luego descarta ese trozo y pasa al siguiente. También debemos recordar buscar la superposición entre cada fragmento.Escribí un código para hacer esto (Se supone que la cadena grande que se buscará, word
es un múltiplo de nuestra longitud de cadena máxima manejable, max_length
, tendrá que ajustar el código para también verificar el resto al final, si esto es no es el caso):
def split_find(word,search_words,max_length):
number_sub_trees = len(word)/max_length
matches = {}
for i in xrange(0,number_sub_trees):
stree = suffixtree.SuffixTree(word[max_length*i:max_length*(i+1)])
for search in search_words:
if search not in matches:
match = stree.find_substring(search)
if match > -1:
matches[search] = match + max_length*i,i
if i < number_sub_trees:
match = word[max_length*(i+1) - len(search):max_length*(i+1) + len(search)].find(search)
if match > -1:
matches[search] = match + max_length*i,i
return matches
word=get_string(4**12)
search_words = ['AAAAAAAAAAAAAAAA'] #list of all words to find matches for
max_length = 4**10 #as large as your machine can cope with (multiple of word)
print split_find(word,search_words,max_length)
En este ejemplo I limitar la longitud árbol de sufijos max a la longitud 4^10, que necesita alrededor de 700 MB. Usando este código, para una cadena de 4^12 de longitud, 10 millones de búsquedas deberían tomar alrededor de 13 horas (búsquedas completas, con cero coincidencias, por lo que si hay coincidencias, será más rápido). Sin embargo, como parte de esto, necesitamos construir 100 árboles de sufijos, que tomarán aproximadamente.100 * 41 segundos = 1 hora.
Así que el tiempo total de ejecución es de alrededor de 14 horas, sin problemas de memoria ... Gran mejora en 9.5 años. Tenga en cuenta que estoy ejecutando esto en una CPU de 1.6GHz con 1GB de RAM, ¡así que debería poder hacerlo mucho mejor que esto!
No estoy particularmente familiarizado con los árboles de sufijo y su implementación no me da pistas sobre cómo se supone que debe funcionar. Te sugiero que uses una biblioteca, p. [pytst] (http://nicolas.lehuen.com/category/pytst/). – MattH
Sugerencia: una estructura de árbol implicaría dictados anidados. –