Ваша функция построения таблицы переходов просто не проверяет стрелки на префиксы. Мы хотим иметь возможность искать для каждой позиции в игле длину самого длинного возможного правильного префикса иглы, ведущей в (но не включая) это положение, кроме начала полного префикса на needle[0]
, который просто не соответствует; это то, как далеко мы должны вернуться в поиске следующего матча. Следовательно, каждая запись в таблице переходов (скажем, table[i]
) точно равна длине максимально длинного правильного префикса иглы, который также является префиксом подстроки, заканчивающейся на needle[i - 1]
.
Первые две записи в таблице переходов - это -1 и 0, так как a) несоответствие в начале шаблона не приводит к обратному отслеживанию (или, другими словами, префикс нулевой длины не может иметь никаких надлежащих префиксов или суффиксы) и б) считается, что пустая строка имеет длину 0.
Для более подробной информации, пожалуйста, посмотрите Википедию или учебник по алгоритмам.
Код для выполнения вышесказанного:
int *build_jump_table(const char * target)
{
if(!target)
return NULL;
int *table = new int[strlen(target) + 1];
if(!table)
return NULL;
table[0] = -1; /* unused by the matcher, just used here */
for(int i = 0; target[i] != '\0'; i++) {
table[i+1] = table[i] + 1;
while(table[i+1] > 0 && target[i] != target[table[i+1] - 1]) {
table[i + 1] = table[table[i + 1] - 1] + 1;
}
}
return table;
}
, что довольно многословно и может быть значительно упрощено, если вы понимаете концепцию таблицы прыжков.