Но по-прежнему сомневаюсь, что регэксп самостоятельно определит такое дверь|дом|дюна|динамит
По идее такой регэсп превратится в дерево с одной вершиной, одной ветвью (с буквой "д") к узлу, 4-я ветвями (с 4-я буквами) из него к 4-м разным узлам следующего уровня и потом из каждого этого узла ещё цепочка ветвей и узлов разной длины уже без ветвлений до конечного листа (соответствующего слова). Реализация КА обрабатывающего это дерево может быть разной, но в общем виде будет похожа на:
for(i=0;i<len;i++)//цикл прохода по буквам всего текста, разбиение на слова для простоты не приведено
switch (state) {
case 0://ждём первую букву искомых слов
switch (s[i]) {
case 'д': state=1; break;//проверка слова дверь
case 'д': state=1; break;//проверка слова дом
case 'д': state=1; break;//проверка слова дюна
case 'д': state=1; break;//проверка слова динамит
};
break;
case 1://проверяем вторую букву искомых слов, причём первая была точно "д"
switch (s[i]) {
case 'в': state=2; break;//проверка слова дверь
case 'о': state=3; break;//проверка слова дом
case 'ю': state=4; break;//проверка слова дюна
case 'и': state=5; break;//проверка слова динамит
default: state=0;//неподходящая буква
};
break;
case 2://проверяем третью букву слова дверь
if (s[i]=='е') state=6; else state=0;//проверка слова дверь
break;
case 3://проверяем третью букву слова дом
switch (s[i]) {
case 'м': return 2;//проверка слова дом, нашли второе искомое слово!
default: state=0;//неподходящая буква
};
break;
case 4://проверяем третью букву слова дюна
state=(s[i]=='н')?7:0;//проверка слова дюна
break;
...
};
Разные варианты кодирования условных операторов показаны специально, функциональность их (в контексте обработки КА) одинакова.
Так вот, даже если построитель КА по регэспу совсем тупой и не исключил дублирование четырёх одинаковых ветвей из state 0 (что в общем-то совершенно нереально по самому принципу минимизации КА), то они будут убиты оптимизирующим компилятором.
Это и есть ответ на Ваш вопрос определит ли и будет ли быстрее. Да, определит и будет.
Подчеркну, любой КА (без памяти) можно представить в виде такого вот длинного switch, просто описываете каждое его уникальное состояние и условия переходов между ними (как в первых двух case выше) и всё, больше ни о чём думать не надо. Правда для сложных паттернов при ошибке текущей буквы переход часто будет в не в state 0, а в другое, которое является подстрокой уже найденной части слова. Пример:
проломить|ломать, после получения на вход
пролом и появлении буквы
а возврат будет не к ожиданию любой из букв
п|л, а к ожиданию буквы
т уже в слове
ломать, т.к. полученная подстрока
пролома включает и начало слова
ломать. Но это уже тонкость на Ваш вопрос не влияющая, просто Вам для информации что не всё так просто как кажется на первый взгляд.
PS. Для любителей чистоты и полноты выкладываемого кода: да, код не полный и даже может содержать незначительные для понимания принципа работы ошибки/описки. Я его не проверял, это лишь иллюстрация принципа реализации одного из видов КА (без памяти).