Para resolver esse problema vamos procurar uma solução com programação dinâmica.
Vamos charmar a string de entrada de , e considerar a tabela , aonde indica a quantidade mínima de inserções para tornar o intervalo um palíndrome.
Para a recursão podemos considerar os seguintes casos:
- : Não necessitamos inserir nenhum caractere, nem na posição nem na posição , então
- : Devemos inserir um caracter ou na posição ou na posição , então quando inserirmos vamos procurar em qual desses lugares inserir custa menos, então
- Caso : Então caímos em um caso base, e então
Assim podemos fazer essa recursão partindo de , e esse será nosso resultado.
Código para melhor entendimento:
OBS: A questão original requeria um uso de Memory Trick para economizar memória, e é por isso o código abaixo usa um vetor em vez de , e também é por isso que está sendo feita de forma bottom-up.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// solucao por Lucio Cardoso | |
#include <bits/stdc++.h> | |
using namespace std; | |
int main(void) | |
{ | |
ios_base::sync_with_stdio(false); | |
cin.tie(0); | |
int n; | |
string s; | |
cin >> n >> s; | |
int dp[2][n+1]; | |
for (int i = n; i >= 1; i--) | |
{ | |
for (int j = i; j <= n; j++) | |
{ | |
if (i == j) | |
dp[i%2][j] = 1; | |
else if (j == i+1) | |
{ | |
if (s[i-1] == s[j-1]) dp[i%2][j] = 2; | |
else dp[i%2][j] = 1; | |
} | |
else | |
{ | |
if (s[i-1] == s[j-1]) dp[i%2][j] = 2+dp[(i+1)%2][j-1]; | |
else dp[i%2][j] = max(dp[(i+1)%2][j], dp[i%2][j-1]); | |
} | |
} | |
} | |
cout << n-dp[1][n] << "\n"; | |
} |