题目背景
IOI2000第一题
题目描述
回文词是一种对称的字符串。任意给定一个字符串,通过插入若干字符,都可以变成回文词。此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数。
比如 “Ab3bd”插入2个字符后可以变成回文词“dAb3bAd”或“Adb3bdA”,但是插入少于2个的字符无法变成回文词。
注:此问题区分大小写
输入输出格式
输入格式:
一个字符串(0<strlen<=1000)
输出格式:
有且只有一个整数,即最少插入字符数
输入输出样例
输入样例#1:
Ab3bd
输出样例#1:
2分析:比较经典的区间dp题,设f[i][j]表示第i到j位要添加多少个字符才能满足要求,如果s[i] == s[j],那么f[i][j] = f[i + 1][j-1],否则,f[i][j] = min(f[i + 1][j],f[i][j-1]) + 1.先预处理出所有长度为2的字符串,然后从小区间到大区间递推.
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> #include <string> using namespace std; string s; int dp[1010][1010]; int main() { cin >> s; for (int i = 0; i < s.size(); i++) for (int j = i; j < s.size(); j++) dp[i][j] = 1000000000; for (int i = 0; i < s.size(); i++) dp[i][i] = 0; for (int i = 0; i < s.size() - 1; i++) { if (s[i] == s[i + 1]) dp[i][i + 1] = 0; else dp[i][i + 1] = 1; } for (int j = 2; j < s.size(); j++) for (int i = 0; i + j < s.size(); i++) { int k = i + j; if (s[i] == s[k]) dp[i][k] = dp[i + 1][k - 1]; else dp[i][k] = min(dp[i + 1][k], dp[i][k - 1]) + 1; } printf("%d ", dp[0][s.size() - 1]); return 0; }