1 /*
2 * DA-term-Palindrome.cpp
3 *
4 * DP
5 *
6 * 动态规划求解。
7
8 设ch[1]..ch[n]表示字符串1至n位,i为左游标,j为右游标 ,则i从n递减,j从i开始递增。
9 min[i][j]表示i和j之间至少需要插入多少个字符才能对称,初始置全0 ,我们最终需要得到的值是min[1][n].
10 则
11 if(ch[i]==ch[j]) //如果两个游标所指字符相同,向中间缩小范围
12 min[i][j]=min[i+1][j-1];
13 else
14 min[i][j] = 1 + (min[i+1][j]和min[i][j-1]中的较小值); //如果不同,典型的状态转换方程
15
16 *
17 */
18
19 #include <cstdio>
20 using namespace std;
21
22 const int maxn = 5000 + 5;
23
24 int len, dp[3][maxn] = {}; //循环数组,否则MTL
25 // dp[k][i] : 长度为k、起点为i的子串变成回文串的最小加字数(k处为循环数组)
26 //对应上面的 min[i][i+k-1]
27 char str[maxn];
28
29
30 int main(){
31 scanf("%d%s", &len, str);
32
33
34 //k_0 : 当前长度; k_1: 当前长度-1; k_2:当前长度-2
35 int k, i, j, k_0 = 2, k_1 = 1, k_2 = 0;
36 for(k=2; k<=len; k++){
37 for(i=len-k; i>=0; i--){
38 j = i + k - 1;
39
40 if(str[i] == str[j]) dp[k_0][i] = dp[k_2][i+1];
41 else{
42 dp[k_0][i] = dp[k_1][i];
43 if(dp[k_0][i] > dp[k_1][i+1]) dp[k_0][i] = dp[k_1][i+1];
44 dp[k_0][i]++;
45 }
46 }
47 k_0 = (k_0 + 1) % 3; //update
48 k_1 = (k_1 + 1) % 3;
49 k_2 = (k_2 + 1) % 3;
50 }
51 printf("%d\n", dp[k_1][0]);
52
53
54 return 0;
55 }