Нужно по набору (мета)символов находить все совпадения в заданной строке. Метасимвол всего один — * (0 или более произвольных символов). Например, для a*a в строке ababa должны быть найдены:
aba, ababa, aba
Писать свой движок регулярок смысла нет, т.к., как я понимаю, регулярки умеют распозновать только одно совпадение за раз, а здесь, например, нужно на втором символе «a» определить как первое совпадение, как потенциальное начало другого, и еще продолжение третьего (начиная с первой «a»), т.к. перед ним еще есть «*».
Какие эффективные способы решения для этого существуют?
В книгах «Практика программирования» (где про grep) и «Идеальный код» (первая глава) приводится реализация подмножества регулярных выражений объёмом в 35 строк. Я бы для начала переделал его (код одинаковый) под задачу и посмотрел на скорость. Если будет слишком медленно, то думать дальше (хотя при m* должно получиться в районе bigomega(N^m), т.е. не быстро в любом случае).
Тот код в 35 строк я, кажется, уже видел, когда искал что-то по теме. Можно попробовать просто удалять m встречающихся подряд * до одной. А как подобная задача обычно решается? Наверняка же реализованы уже хорошие методы для overlapping matches.
И если использовать тот код (если я правильно помню), то оно будет доходить только до первого совпадения, не считая еще того, что нужно будет проверить варианты для подстрок с началами во всех возможных местах (string.length).
Из паттерна делаем строку с 2 нулями на конце, заменяем '*' нулем. Ищем первый образец, от следующего за концом найденного символа ищем следующий образец. Повторяем, пока не закончится строка образцов. Получив искомый фрагмент, сдвигаем начало поиска последнего (n-го) фрагмента образца на 1, повторяем, собирая совпавшее. Повторяем для n-1, n-2,.. фрагментов образца рекурсивно.
И если использовать тот код (если я правильно помню), то оно будет доходить только до первого совпадения, не считая еще того, что нужно будет проверить варианты для подстрок с началами во всех возможных местах (string.length).
Всё так, но если убрать пару проверок, то он станет обходить все варианты. Надо просто продолжать искать до конца строки, даже если уже видели совпадение. И там вроде не жадный оператор * был, его надо научить идти дальше после успешного совпадения.
Какие эффективные способы решения для этого существуют?
Добавлю к предложенным еще пару способов, с предварительной обработкой.
Если маска известна на этапе компиляции и нужно искать совпадения в разных строках, то можно генерировать код для матчинга. То есть сделать что-то типа re2c, только проще.
Если строка для поиска постоянна, а меняются только маски, можно попробовать матчить с помощью суффиксного массива. Он дает быстрый (log(N)) поиск подстроки (точнее поиск смещения подстроки в строке) + подстроки в нем отсортированы. Для строки 'ababa' и подстроки 'a' получим индексы 1, 3, 5, уже почти готовое решение.