Ищем подстроку в строке за линейное время.
F[n] - failure function, длина сдвига для подстроки с 0 символа до n-1
int m - длина подстроки
int n - длина строки
char* pattern - искомая подстрока
char* text - строка, в которой будем искать
Код:
int F[MAX]; void preKMP (char* pattern, int m){ F[0]=F[1]=0; for (int i=2; i<=m; ++i){ // j - индекс прошлого совпадения с префиксом int j=F[i-1]; for (;;){ // если данный символ i-1 расширяет данное совпадение j, то устанавливаем соответствующее значение в F[i-1] if(pattern[j]==pattern[i-1]){ F[i]=j+1; break; } // если дошли до пустой строки if(j==0){ F[i]=0; break; } // переходим к следующему совпадению j=F[j]; } } } // возвращает индекс, с которого начинается первое полное совпадение int KMP (char* pattern, int m, char* text, int n){ preKMP(pattern, m); int j=0; // начальная позиция в подстроке int i=0; // начальная позиция в строке for (;;){ // достигнут конец строки? if (i==n) break; // если данные символы строки и искомого образца совпадают.... if (text[i]==pattern[j]){ j++; // переходим к следующему символу образца i++; // и следующему символу строки if(j==m){ // нашли! return i-m; } } else if(j>0){ // если можно перейти к другому префиксу, перейдем j=F[j]; } else // если нельзя, переходим к следующему символу строки i++; } return -1; }