1. 1. 题目
    1. 1.1. [IOI2000] 回文字串
  2. 2. 题解
  3. 3. 代码

题目

[IOI2000] 回文字串

回文词是一种对称的字符串。任意给定一个字符串,通过插入若干字符,都可以变成回文词。此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数。

比如 Ab3bd\verb!Ab3bd! 插入 22 个字符后可以变成回文词 dAb3bAd\verb!dAb3bAd!Adb3bdA\verb!Adb3bdA!,但是插入少于 22 个的字符无法变成回文词。

注意:此问题区分大小写。

记字符串长度为 ll

对于全部数据,0<l10000<l\le 1000

题解

设f[i][j]表示把f[i][j]变成回文的最少步数

然后分三种情况转移

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include<bits/stdc++.h>

using namespace std;
const int N = 1010;
char a[N];
int f[N][N];

int read()
{
int f = 1, x = 0;
char ch = getchar();
while(ch < '0' || ch > '9')
{
if(ch == '-') f = -1;
ch = getchar();
}

while(ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return f * x;
}

int main()
{
scanf("%s", a + 1);

int n = strlen(a + 1);
for(int i = 1;i <= n;i++)
{
f[i][i] = 0;
}

for(int i = 1;i < n;i++)
{
if(a[i] == a[i + 1])
{
f[i][i + 1] = 0;
}
else
{
f[i][i + 1] = 1;
}
}

for(int L = 3;L <= n;L++)
{
for(int i = 1;i + L - 1 <= n;i++)
{
int j = i + L - 1;
f[i][j] = min(f[i][j - 1] + 1, f[i + 1][j] + 1);

if(a[i] == a[j])
f[i][j] = min(f[i + 1][j - 1], f[i][j]);
}
}
cout << f[1][n];
return 0;
}