Algoritmo para generar una lista de pares recurrentes

Dado un archivo de texto en el formato siguiente, cada línea es una lista de hasta 50 nombres. Escribir un programa produce una lista de pares de nombres que aparecen juntos en al menos cincuenta listas diferentes.

Tyra,Miranda,Naomi,Adriana,Kate,Elle,Heidi
Daniela,Miranda,Irina,Alessandra,Gisele,Adriana

En la muestra anterior, Miranda y Adriana aparecen juntas dos veces, pero cada otra pareja aparece solo una vez. Debería devolver "Miranda, Adriana\n". Se puede devolver una solución aproximada con listas que aparecen al menos 50 veces con alta probabilidad.

Estaba pensando en la siguiente solución:

  1. Generar un Map <Pair,Integer> pairToCountMap, después de leer el archivo.

  2. Iterar a través del mapa e imprimir aquellos con recuentos> = 50

¿Hay una mejor manera de hacer esto? El archivo podría ser muy grande y no estoy seguro de qué significa la solución aproximada. Cualquier enlace o recurso sería muy apreciado.

preguntado el 30 de junio de 12 a las 15:06

2 Respuestas

Primero, supongamos que los nombres tienen una longitud limitada, por lo que las operaciones en ellos son de tiempo constante.

Su respuesta debería ser aceptable si cabe en la memoria. Si usted tiene N líneas con m nombres de cada uno, su solución debe tomar O(N*m*m) para completar.

Si ese conjunto de datos no cabe en la memoria, puede escribir los pares en un archivo, ordenar ese archivo mediante una ordenación por combinación y luego escanear para contar los pares. El tiempo de ejecución de esto es O(N*m*log(N*m)), pero debido a los detalles sobre la velocidad de acceso al disco, se ejecutará mucho más rápido en la práctica.

Si tiene un clúster distribuido, podría usar un MapReduce. Funcionaría de manera muy similar a la última solución.

En cuanto al enfoque estadístico, supongo que significan recorrer la lista de archivos para encontrar la frecuencia de cada nombre y la cantidad de líneas con diferentes números de nombres en ellas. Si asumimos que cada línea es una variedad aleatoria de nombres, usando estadísticas podemos estimar cuántas intersecciones hay entre cualquier par de nombres comunes. Esto será aproximadamente lineal en la longitud del archivo.

Respondido 01 Jul 12, 17:07

¿Qué quiere decir con 'escribir los pares en un archivo'? ¿Eso significa que tenemos que escribir m^2 artículos por línea de entrada? - unkulunkulu

@unkulunkulu Exactamente. Escribe siempre el par de nombres ordenados. - tímidamente

@btilly Tengo problemas para entender el enfoque estadístico. ¿Puede señalarme algunos enlaces o un tema de Wikipedia? Gracias. - zc22

@project.zylon La dificultad de las estadísticas depende de lo sofisticado que quieras ser. El caso más sencillo es cuando las listas son aleatorias y pueden repetir nombres. En ese caso si la palabra A tiene proporción p de las palabras, y la palabra B tiene proporción q, luego en una lista de i palabras la probabilidad de que ambas aparezcan es (1-q)^i + (1-p)^i - (1 - p - q)^i. Sume las probabilidades de todas las listas en las que podrían aparecer, y tendrá el número esperado de pares en los que podrían estar. Más allá de ese caso simplificado, todo es una cuestión de cuán precisa necesita que sea su heurística. - tímidamente

Una heurística mejorada para el caso sin repetición donde ninguna palabra ocupa una gran proporción de todas las palabras es que la probabilidad de que ambas aparezcan en una lista de longitud i is i*i*p*q. Esta estimación no es exacta, pero puede estar lo suficientemente cerca. - tímidamente

Para cada nombre, puede obtener la lista de los números de línea donde aparece (use una tabla hash para almacenar los nombres), luego, para cada par de nombres, obtenga el tamaño de la intersección de los índices de línea correspondientes (en el caso de dos secuencias crecientes). este es el tiempo lineal). Digamos que la longitud de un nombre está limitada por una constante. entonces si tienes N nombres y M líneas, luego construir la lista es como O(MN) y la etapa final es O(N^2 M).

Respondido el 30 de junio de 12 a las 15:06

+1, pero creo que solo te refieres a "intersección" en lugar de "la mayor subsecuencia común" (que funciona pero es un problema más general). Mantendría las listas de líneas ordenadas y usaría una combinación de listas para encontrar esta intersección. - j_random_hacker

@j_random_hacker, acababa de regresar de resolver uno de los mayores problemas comunes de subsecuencias, así que mi mente me atrapó, la intersección es simplemente lógica para este problema, estoy de acuerdo contigo. - unkulunkulu

Su tiempo de ejecución no es mejor que el de él en el mejor de los casos, y es sustancialmente más lento en el caso de que haya muchos pares de nombres que no aparecen en ninguna línea en común. - tímidamente

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.