DP起手练习2

题目描述

luoguP1435

回文词是一种对称的字符串。任意给定一个字符串,通过插入若干字符,都可以变成回文词。此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数。比如 “Ab3bd”插入2个字符后可以变成回文词“dAb3bAd”或“Adb3bdA”,但是插入少于2个的字符无法变成回文词。

注:此问题区分大小写.

输入格式

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

输出格式

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

输入输出样例

输入 #1
Ab3bd
输出 #1
2

思路

这道题正面思考直接在这个串上DP是很麻烦的,但我们知道:所谓回文字串就是正着或倒着看都一样,所以我们可以构造这个串的倒串,然后求出这两个串的最长公共子序列,而剩下的便是要添加的字串.及最后的答案为 l e n − f [ n ] [ n ] {len-f[n][n]} lenf[n][n].(len表示串的总长, f [ i ] [ j ] {f[i][j]} f[i][j]表示串的从1开始长度为 i {i} i子串与其倒串的从1开始长度为 j {j} j子串的最长公共子序列),然后这就变成了经典的LCS问题.
DP转移方程:(s1为原串,s2为倒串)
if( s 1 [ i ] = s 2 [ j ] {s1[i]=s2[j]} s1[i]=s2[j]) f [ i ] [ j ] {f[i][j]} f[i][j]= m a x ( f [ i ] [ j ] , f [ i − 1 ] [ j − 1 ] + 1 ) {max(f[i][j],f[i-1][j-1]+1)} max(f[i][j],f[i1][j1]+1);
else f [ i ] [ j ] {f[i][j]} f[i][j]= m a x ( f [ i − 1 ] [ j ] , f [ i ] [ j − 1 ] ) {max(f[i-1][j],f[i][j-1])} max(f[i1][j],f[i][j1]);

代码

#include<bits/stdc++.h>
#define N 1005
using namespace std;

int len,zhi,ans=0,f[N][N];
char s1[2002],s2[2002];

int main()
{
	scanf("%s",s1+1);
	len=strlen(s1+1);
	for(int i=1;i<=len;i++)//构造倒串
	s2[i]=s1[len-i+1];
	for(int i=1;i<=len;i++)//核心代码
		for(int j=1;j<=len;j++)
		{
			if(s1[i]==s2[j])
			f[i][j]=max(f[i][j],f[i-1][j-1]+1);
			else f[i][j]=max(f[i-1][j],f[i][j-1]);
		}
	cout<<len-f[len][len]<<endl;
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liaoxiyan123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值