Verilmiş sətrə, palindrom olması üçün minimum sayda simvol əlavə etmək lazımdır. Bunun üçün onun bütün sonluqları (suffiksləri) arasında ən böyük palindromu tapmaq, sonra bu palindromun başlanğıcına qədər olan prefiksi götürüb, onu tərs çevirmək və ilkin sətrə əlavə etmək lazımdır.
Məsələn, sətrinin ən böyük palindromik sonluğu -dir. Ona qədər olan prefiks — -dir, onu tərs çeviririk (nəticədə alınır) və ilkin sətrə əlavə edirik.
rs = reverse(s) + s sətrinə baxaq. Onun üçün -funksiyasını hesablayaq.
i + z_i = 2n bərabərliyi ödənən ən kiçik indeksini (elə ki, i \ge n) tapaq. Bu zaman belə indekslər arasında z_i qiyməti maksimal olacaq. İlkin sətri palindroma çevirmək üçün ona əlavə edilməli olan minimum simvol sayı n - z_i-yə bərabərdir.
"" sətri üçün (uzunluq n = 6) axtarılan indeks i = 9-dur, çünki 9 + z_9 = 9 + 3 = 12 = 2 * 6.
Nümunə
Birinci nümunəyə baxaq. reverse(s) + s = "bba" + "abb" = "bbaabb" sətri üçün -funksiyasını hesablayaq.
i + z_i = 2n bərabərliyi ödənən ən kiçik i~(i ≥ n) indeksi i = 4-dür. Doğrudan da: 4 + z_4 = 4 + 2 = 6 = 2 * 3. Onda cavab n - z_i = 3 - 2 = 1-ə bərabərdir. Yəni, "" sətrinə palindrom "" almaq üçün cəmi bir '' simvolu əlavə etmək kifayətdir.
Alqoritmin realizasiyası
z funksiyası sətri üçün -funksiyasını qurur və qaytarır.
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;
}Proqramın əsas hissəsi. Giriş sətri -i oxuyuruq.
cin >> n;
cin >> s;rs = reverse(s) + s sətrini qururuq.
rs = s;
reverse(rs.begin(), rs.end());
rs += s;sətrinin -funksiyasını hesablayırıq.
z = zfun(rs);i + z_i = 2n bərabərliyi ödənən ən kiçik i~(i \ge n) indeksini tapırıq. Bütün belə indekslər arasında z_i qiyməti ən böyük olacaq.
for (i = n; i < rs.size(); i++)
if (i + z[i] == 2 * n)
{Cavabı çıxarırıq.
cout << n - z[i] << endl;
break;
}