回文串问题------动态规划

一个字符串,如果从左到右读和从右到左读是完全一样的,比如"aba",我们称其为回文串。现在给你一个字符串,可在任意位置添加字符,求最少添加几个字符,才能使其变成一个回文串。

输入格式:

任意给定的一个字符串,其长度不超过1000.

输出格式:

能变成回文串所需添加的最少字符数。

输入样例:

在这里给出一组输入。例如:

Ab3bd
Abb

输出样例:

在这里给出相应的输出。例如:

2
1

 

动态规划解法

状态定义
  • dp[i][j] 表示将子串 s[i..j](包含 i 和 j)变成回文串所需的最少添加字符数。
转移方程
  • 如果 s[i]=s[j]:
    • 两端字符已匹配,直接看内层子串:dp[i][j]=dp[i+1][j−1]。
  • 如果 s[i]≠s[j]:
    • 可以在 i 端添加 s[j],使 i 匹配 j,然后处理 s[i+1..j]:dp[i][j]=dp[i+1][j]+1;
    • 或者在 j 端添加 s[i],使 j 匹配 i,然后处理 s[i..j−1]:dp[i][j]=dp[i][j−1]+1;
    • 取最小值:dp[i][j]=min(dp[i+1][j],dp[i][j−1])+1。
初始条件
  • dp[i][i]=0(单个字符已是回文)。
  • dp[i][i−1]=0(空串是回文,方便边界处理)。
目标
  • dp[0][n−1],其中 n 是字符串长度。

举例说明:

 s="Ab3bd"

1.计算长度为 1 的子串(初始条件) 

  • dp[0][0]=0("A" 是回文)
  • dp[1][1]=0("b")
  • dp[2][2]=0("3")
  • dp[3][3]=0("b")
  • dp[4][4]=0("d")

 2.计算长度为 2 的子串

  • dp[0][1]="Ab"=1
  • dp[1][2]="b3"=1
  • dp[2][3]="3b"=1
  • dp[3][4]="bd"=1

 3.计算长度为 3 的子串

  • dp[0][2]="Ab3":

s[0]=′A′,s[2]=′3′,不相等。

dp[1][2]=1("b3"),dp[0][1]=1("Ab")。

dp[0][2]=min⁡(dp[1][2],dp[0][1])+1=min⁡(1,1)+1=2。

  •  dp[1][3]="b3b"
  • dp[2][4]="3bd"

4. 计算长度为 4 的子串

  • dp[0][3]="Ab3b"
  • dp[1][4]="b3bd"

5.最后就是计算整个字符串的长度

#include
using namespace std;
int main()
{
	string s;
	while(cin>>s)
	{
		int n=s.length();
		int dp[n][n]={0};
		//从短到长开始记录子问题结果,先从长度为 2 的子串开始计算 
		for(int len=2;len<=n;len++)
		{
			for(int i=0;i+len-1

 希望在加深俺记忆理解的同时也能帮助到各位同志,新手小白练手,若有不对之处欢迎评论区留言,谢谢!回文串问题------动态规划_第1张图片

你可能感兴趣的:(动态规划,算法,蓝桥杯,数据结构)