КМП#1498

КМП (Розбір)

У задачі необхідно реалізувати алгоритм Кнута-Морріса-Пратта пошуку в тексті підрядка.

Реалізація алгоритму

Оголосимо наступні змінні:

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;