ABB#9759

ABB (Розбір)

До заданого рядка потрібно додати мінімальну кількість символів, щоб він став паліндромом. Для цього потрібно знайти найбільший паліндром серед усіх його суфіксів, потім взяти префікс до початку цього паліндрома, розвернути його і приписати до вихідного рядка.

Наприклад, найбільшим паліндромним суфіксом рядка є . Префікс до нього — , розвертаємо його (отримуємо ) і приписуємо до вихідного рядка.

Розглянемо рядок rs = reverse(s) + s. Обчислимо для нього -функцію.

Знайдемо найменший індекс (такий, що i \ge n), для якого виконується рівність i + z_i = 2n. При цьому значення z_i буде максимальним серед таких індексів. Мінімальна кількість символів, яку необхідно дописати до вихідного рядка, щоб отримати паліндром, дорівнює n - z_i.

Для рядка "" (довжина n = 6) потрібний індекс i = 9, оскільки 9 + z_9 = 9 + 3 = 12 = 2 * 6.

Приклад

Розглянемо перший приклад. Обчислимо -функцію для рядка reverse(s) + s = "bba" + "abb" = "bbaabb".

Найменшим індексом i~(i ≥ n), для якого виконується рівність i + z_i = 2n, є i = 4. Дійсно: 4 + z_4 = 4 + 2 = 6 = 2 * 3. Тоді відповідь дорівнює n - z_i = 3 - 2 = 1. Тобто, до рядка "" достатньо додати один символ '', щоб отримати паліндром "".

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

Функція z будує і повертає -функцію для рядка .

vector<int> zfun(string s)
{
  int i, l, r, len = s.size();
  vector<int> z(len, 0);
  l = r = 0;
  for (i = 1; i < len; i++)
  {
    if (i <= r) z[i] = min(r - i + 1, z[i - l]);
    while (i + z[i] < len && s[z[i]] == s[i + z[i]]) z[i]++;
    if (i + z[i] - 1 > r)
    {
      l = i;
      r = i + z[i] - 1;
    }
  }
  return z;
}

Основна частина програми. Читаємо вхідний рядок .

cin >> n;
cin >> s;

Будуємо рядок rs = reverse(s) + s.

rs = s;
reverse(rs.begin(), rs.end());
rs += s;

Обчислюємо -функцію рядка .

z = zfun(rs);

Знаходимо найменший індекс i~(i \ge n), для якого виконується рівність i + z_i = 2n. Серед усіх таких індексів значення z_i буде найбільшим.

for (i = n; i < rs.size(); i++)
  if (i + z[i] == 2 * n)
  {

Виводимо відповідь.

    cout << n - z[i] << endl;
    break;
  }