[pyar] [JUEGO] Búsqueda de strings

Alejandro Santos listas en alejolp.com
Sab Mayo 3 23:30:52 ART 2014


2014-05-03 11:10 GMT+02:00 Angel Java Lopez <ajlopez2000 en gmail.com>:
> Ahora bien, sea S lo que  buscamos. Lo que yo haria es que a cada S
> distinta, le asignaria un numero natural distinto
>
> f(S) = n
>
> Para cada elemento de L, L[i], prepararia una sarta de bits. El bit n
> estaria prendido, si el S correspondiente a ese n (los S tales que f(S) = n)
> esta contenido en L[i]. (bien podriamos poner que  S = "com", S = "Com", S =
> "COM", ... todos den el mismo n)
>

Suena interesante! Aunque estoy un poco perdido. ¿Cuántos sillones* de
RAM necesitamos para esto? Porque cuando decís:

  f(S) = n

Me imagino algo así:

def f(S):
    return reduce(lambda x, y: ((x << 8) | y), map(ord, reversed(S)), 0)

que basicamente da vuelta el string y convierte el string en un long
de longitud arbitraria. Y para un string chiquito, "Onomatopeya",
tenemos 88 bits.

Hay una forma mucho más fácil de aprovechar el Boyer-Moore que ya
viene con Python. La idea es preprocesar L para que las búsquedas sean
más rápidas.

Hacemos un string W que sea la concatenación en orden de todos los
strings de L, usando un caracter especial como separador, ejemplo:

  L = ["Casa", "Perro", "Gato", ...]
  W = "Casa\nPerro\nGato\n..."

y hacemos una tabla T que nos diga cada elemento donde empieza en el string W:

  T = [0, 5, 11, 16, ... ]

Entonces:

- Averiguar si alguna de los strings de L tiene un substr S
determinado es simplemente: S in W.

- Averiguar cuales son los strings L que tienen un substr S determinado hay que:

1. buscar con W.find la posicion de S
2. hacer una busqueda binaria en T de la posicion
3. Repetir hasta que W.find == -1

En tiempo esto es O(n.m), con n=len(L) y m=promedio de longitud del
string, y gracias a Boyer-Moore el tiempo (casi) no depende de len(S).

En un gráfico hoy me dió esto:

  http://imgur.com/fdyOp2K

El eje horizontal es la longitud del S.

find1 es la version [x for x in L if S in x]

find2 es la versión de los párrafos anteriores.

Hay una tercer opción que es O(log n) con otra tabla adicional de
preprocesado, y él gráfico de tiempo da plano en cero, pero armar esta
tabla me esta tardando asquerosamente demasiado tiempo.

[*] sillones: zillions en argentino.


-- 
Alejandro Santos


More information about the pyar mailing list