Es interesante el problema que planteas. La solución que has desarrollado parece ser efectiva, no he visto los problemas que mencionas (palabras que no aparecen o aparecen repetidas), tan solo un ligero problema con los saltos de línea, y un par de detalles que me llaman la atención de tu implementación:
- Las variables usadas hacen uso de una cantidad considerable de memoria. La variable $texto almacena el texto completo del archivo, la matriz $line almacena todas las líneas, la matriz $words almacena todas las palabras únicas, y la matriz $text almacena todas las palabras de cada línea. Como podrás imaginar, entre más grande sea el archivo de entrada, el consumo de memoria será considerablemente mayor.
- El algoritmo contiene un ciclo principal con una complejidad O(m * n * o) en donde m es el número de palabras del archivo, n el número de líneas y o el número de palabras por línea. Me parece que vale la pena buscar alguna alternativa que reduzca este valor.
Mi propuesta para el problema sería algo como esto:
Código PHP:
$archivo = 'texto.txt';
$da = fopen ($archivo, 'r');
$resultados = array ();
$num_linea = 0;
while (! feof ($da)) {
$num_linea++;
$linea = fgets ($da);
$palabras = array_unique (preg_split ('/\\s+/', $linea, -1,
PREG_SPLIT_NO_EMPTY));
foreach ($palabras as $palabra) {
if (! isset ($resultados[$palabra])) {
$resultados[$palabra] = array ($num_linea);
} else {
$resultados[$palabra][] = $num_linea;
}
}
}
fclose ($da)
// Ordenar resultados
ksort ($resultados);
// Recolectar resultados en un bufer
$return = '';
foreach ($resultados as $palabra => $lineas) {
$return .= "{$palabra} : " . implode (', ', $lineas) . "\n";
}
No lo he probado exhaustivamente pero parece trabajar bien. Quizás te resulte útil en tu script.