IOI2000 回文字串

题目:回文字串

网址:https://www.luogu.com.cn/problem/P1435

题目描述

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

比如 “Ab3bd”插入2个字符后可以变成回文词“dAb3bAd”或“Adb3bdA”,但是插入少于2个的字符无法变成回文词。

注:此问题区分大小写

输入格式

一个字符串(0<strlen<=1000)

输出格式

有且只有一个整数,即最少插入字符数

输入输出样例
输入
Ab3bd
输出
2

本题使用DP。
设dp[i, j]代表区间[i, j]变为回文字串所需要的最小操作数量。

分别向最左端及最右端插入一个相等的字符,有dp[i, j] = min(dp[i + 1, j] + 1, dp[i, j - 1])。

由于左右两个字符一样,则有dp[i, j] = min{dp[i, j], dp[i - 1, j - 1]}。

初始化的时候,令dp[i][i] = dp[i + 1][i] = 0(其中0 < i < n)即可(因为单个字符本身就是回文字串;而出现了两个相邻且相同的字符a[i]和a[i + 1],转移时代价为0)。

代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn = 1000 + 5;
char s[maxn];
int n, dp[maxn][maxn] = {};
int main()
{
	scanf("%s", (s + 1));
	n = strlen(s + 1);
	int i, j, len;
	for(i = 1; i <= n; ++ i) dp[i][i] = 0;
	for(len = 2; len <= n; ++ len)
	{
		for(i = 1, j = i + len - 1; j <= n; ++ i, ++ j)
		{
			dp[i][j] = min(dp[i + 1][j] + 1, dp[i][j - 1] + 1);
			if(s[i] == s[j]) dp[i][j] = min(dp[i][j], dp[i + 1][j - 1]);
		}
	}
	printf("%d
", dp[1][n]);
	return 0;
}
原文地址:https://www.cnblogs.com/zach20040914/p/12852801.html