Но по-прежнему сомневаюсь, что регэксп самостоятельно определит такое дверь|дом|дюна|динамит
По идее такой регэсп превратится в дерево с одной вершиной, одной ветвью (с буквой "д") к узлу, 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. Для любителей чистоты и полноты выкладываемого кода: да, код не полный и даже может содержать незначительные для понимания принципа работы ошибки/описки. Я его не проверял, это лишь иллюстрация принципа реализации одного из видов КА (без памяти).