У задачі необхідно реалізувати алгоритм Кнута-Морріса-Пратта пошуку в тексті підрядка.
Реалізація алгоритму
Оголосимо наступні змінні:
— рядок, в якому потрібно знайти всі входження шаблону .
— підрядок (шаблон), який ми шукаємо в рядку .
— префікс-функція для рядка .
— список всіх позицій в рядку , з яких починається входження підрядка .
string text, word;
vector<int> p, pos;Функція MaxBorderArray обчислює префікс-функцію рядка і зберігає її значення в масиві .
void MaxBorderArray(string &s)
{
p.resize(s.size());
for (int i = 1; i < s.size(); i++)
{
int j = p[i - 1];
while ((j > 0) && (s[i] != s[j])) j = p[j - 1];
if (s[i] == s[j]) j++;
p[i] = j;
}
}Функція kmp реалізує алгоритм Кнута — Морріса — Пратта. Всі індекси початку входжень рядка в текст зберігаються в масиві .
void kmp(string &word, string &text)
{
MaxBorderArray(word);
for (int i = 0, j = 0; i < text.size(); i++)
{
while (j && (text[i] != word[j])) j = p[j - 1];
if (text[i] == word[j]) j++;Якщо індекс досяг останнього символу рядка , це означає, що в тексті знайдено повне входження слова . Початкова позиція знайденого входження дорівнює i - j + 1 (нумерація символів починається з нуля).
if (j == word.size()) pos.push_back(i - j + 1);
}
}Основна частина програми. Читаємо вхідні рядки.
cin >> text;
cin >> word;Запускаємо алгоритм Кнута-Морріса-Пратта.
kmp(word, text);Виводимо знайдені позиції входження.
for (auto x : pos)
cout << x << " ";
cout << endl;