Первое решение TXR Lisp (http://www.nongnu.org/txr):
(defvar tg-hash (hash)) ;; tg == "trigraph"
(unless (= (len *args*) 2)
(put-line `arguments required: <wordfile> <textfile>`)
(exit nil))
(defvar wordfile [*args* 0])
(defvar textfile [*args* 1])
(mapcar (lambda (line)
(dotimes (i (len line))
(push line [tg-hash [line i..(succ i)]])
(push line [tg-hash [line i..(ssucc i)]])
(push line [tg-hash [line i..(sssucc i)]])))
(file-get-lines textfile))
(mapcar (lambda (word)
(if (< (len word) 4)
(if [tg-hash word]
(put-line word))
(if (find word [tg-hash [word 0..3]]
(op search-str @2 @1))
(put-line word))))
(file-get-lines wordfile))
Стратегия здесь заключается в том, чтобы сводить совокупность слов в хеш-таблицу, которая индексируется на отдельных символах, орграфах и триграфах, встречающихся в строках, связывая эти фрагменты со строками. Затем, когда мы обрабатываем список слов, это уменьшает усилия поиска.
Во-первых, если слово короткое, не более трех символов (вероятно, встречается в китайских словах), мы можем попытаться получить мгновенное совпадение в хеш-таблице. Если совпадений нет, слово не в корпусе.
Если слово длиннее трех символов, мы можем попытаться найти совпадение для первых трех символов. Это дает нам список строк, которые содержат совпадение для триграфа. Мы можем искать эти строки исчерпывающе, чтобы увидеть, какие из них соответствуют слову. Я подозреваю, что это значительно уменьшит количество строк, которые нужно искать.
Мне нужны ваши данные или что-то, что их представляет, чтобы можно было увидеть, на что похоже поведение.
Пример прогона:
$ txr words.tl words.txt text.txt
water
fire
earth
the
$ cat words.txt
water
fire
earth
the
it
$ cat text.txt
Long ago people
believed that the four
elements were
just
water
fire
earth
(TXR читает UTF-8 и выполняет все операции со строками в Юникоде, поэтому тестирование с использованием символов ASCII допустимо.)
Использование ленивых списков означает, что мы не храним, например, весь список из 300 000 слов. Хотя мы используем функцию Lisp mapcar
, список создается на лету, и поскольку мы не храним ссылку на заголовок списка, он пригоден для сбора мусора.
К сожалению, мы должны хранить корпус текста в памяти, потому что хеш-таблица связывает строки.
Если это проблема, решение может быть отменено. Просканируйте все слова, а затем лениво обработайте текстовый корпус, помечая те слова, которые встречаются. Тогда устраните все остальное. Я также опубликую такое решение.