题目背景
IOI2000第一题
题目描述
回文词是一种对称的字符串。任意给定一个字符串,通过插入若干字符,都可以变成回文词。此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数。
比如 “Ab3bd”插入2个字符后可以变成回文词“dAb3bAd”或“Adb3bdA”,但是插入少于2个的字符无法变成回文词。
注:此问题区分大小写
输入输出格式
输入格式:一个字符串(0<strlen<=1000)
有且只有一个整数,即最少插入字符数
解答:
本题还是非常简单的,是动态规划的入门级别题目。
两种思路:str为字符串
1.区间dp:设dp[i][j]表示[i,j]变成回文串所需要添加的最少字符数,那么若str[i]==str[j] 则 dp[i][j] = dp[i+1][j-1] ;若str[i] != str[j] 则 dp[i][j] = min(dp[i+1][j], dp[i][j-1]) + 1
2.最长公共子序列的变形:回文串的特征是正过来反过来读一样,那么考虑把字符串反向,反向字符串与原字符串的公共子序列就是所给字符串的最大的回文子串,只需要将剩余部分的字符再添加一遍到合适的位置即可。那么最后的结果就是 字符串长度-最长公共子序列的长度
这里采用的是第一种方法:
#include <stdio.h>
#include <string.h>
const int maxL = 1005;
char str[maxL];
int dp[maxL][maxL];
int min(int a , int b)
{
if (a < b) return a;
return b;
}
int main()
{
scanf("%s",str);
int l = strlen(str);
for (int i = l - 1 ; i >= 1 ; i--)
{
for (int j = i + 1 ; j <= l ; j ++)
{
if (str[i-1] == str[j-1])
{
dp[i][j] = dp[i + 1][j - 1];
}
else {
dp[i][j] = min(dp[i+1][j] , dp[i][j-1]) + 1;
}
}
}
printf("%d", dp[1][l]);
return 0;
}