Как найти вхождения сотен поисковых фраз в большом тексте (PHP, MySQL)?

Дано:

1) Художественный текст размером до 10 мегабайт.
2) Список поисковых фраз (фразы состоят из разного количества слов), который будет пополнятся. Счет идет на сотни фраз.

Необходимо:

1) Найти все вхождения поисковых фраз в тексте.
2) Подсветить вхождения.

В наличии Mysql и PHP. У меня такие вопросы:

1) Как к этой задаче подступиться? Какой способ поиска будет оптимальным?
2) Потянет ли рядовой виртуальный хостинг выполнение такой задачи хотя бы одним пользователем одновременно без нареканий хостера?
  • Вопрос задан
  • 4445 просмотров
Решения вопроса 1
Сложного ничего не вижу. Как то давно, тоже надо было найти в большом тексте (около 15 мб) пару фраз.
1) Поиск осуществлять strpos, начиная с последней найденной позиции. Таким образом Вы получите позиции вхождения фраз в текст - тогда не будет проблем с подсветкой.
2) Если фразы будут добавляться, а текст при этом останется исходным, я бы сделал обработку один раз, сохранил для каждой фразы точки вхождения и при дальнейшей обработке просто добавлял бы новые фразы, искал бы по ним вхождения и сохранял. Это позволит Вам сэкономить ресурсы и раздавать результат большому количеству пользователей.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
ScorpLeX
@ScorpLeX
Если стоит задача не вызвать нареканий хостера, нужно делать очередь, разбивать и ставить текст в очередь на обработку.
Если имеется только mysql и php в принципе нет особой разницы как искать, только нужно понимать, что в алгоритм желательно заложить например usleep дабы не создавать скачки загрузки cpu.
Ответ написан
@klirichek
В принципе, можно попробовать сделать в один проход.
Для каждой фразы делаем ДКА состояний - чтоб ловить поступающие слова и двигать состояние вперёд, если совпадает с ожидающим следующим словом. Если слова закончились - запоминать найденную позицию и сбрасывать состояние. Если новое слово не совпадает - просто сбрасывать состояние.
А дальше - организуем "игру в лото". Проходимся один раз по тексту от начала до конца и "объявляем" всем участвующим ДКА каждое слово. В конце залезаем в них и получаем списки "выигравших" позиций для каждой фразы.
Это в общем. А дальше можно оптимизировать - например, сравнивать не слова, а хэшики от них.
И не "объявлять" каждому "игроку" каждое слово, а собирать у них множество ожидаемых ими хэшиков - и если текущий попадает в множество - двигать состояния у "выигравших", а у всех остальных - сбрасывать.
Ещё шаг - сделать не одно, а два множества. В одном - хэшики тех, что в начальном состоянии (при сбросе они не меняются -> не нужно читать значения заново). Во втором - "играющие".

Здесь нужно побенчить по сравнению с indexof. Последний внутри себя, конечно, будет работать быстрее, чем аналогичный "самописный", однако на определённых параметрах (совокупность размера входного текста вместе с количеством и размером искомых фраз) уже может вполне его обойти за счёт меньшей сложности.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы