简单dp-删除最少字符变成回文串

题目描述:给定一字符串s,求最少删除多少个字符可以使得s成为回文串。例如:s="abca",答案是1.

解题思路:这里提供两种解题方法,第一种是用到上一篇写的LCS(最长公共子串),第二种是直接的dp。
1,第一种思路就是申请s2变量,使得s2是s1的反转,如果是回文串的话,那么就等价于求s2和s1的LCS,例如s1=abca,s2=acba,公共子串的长度为3(aba ,aca),所以需要删除的字符串个数就是4-3=1。关于LCS的方法已经在上一篇详细描述了,这里直接附上代码:
#include
#include
#include
using namespace std;
string s1,s2;
int n;
int c[1000][1000];
int main()
{
	cin >> s1;
	n = s1.length();
	s2 = s1;
	reverse(s2.begin(), s2.end());
	for (int i = 0; i <= n; i++)
	{
		c[i][0] = 0;
	}
	for (int j = 0; j <= n; j++)
	{
		c[0][j] = 0;
	}
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			if (s1[i - 1] == s2[j - 1])
			{
				c[i][j] = c[i - 1][j - 1] + 1;
			}
			else
			{
				int ma = max(c[i - 1][j], c[i][j - 1]);
				c[i][j] = ma;
			}
		}
	}
	cout << n-c[n][n] << endl;
	return 0;
}

2,第二种思路是直接递推,这里需要用到二维数组dp[i][j],这里的i和j指的是从下标为i到j的子串需要删除的字符个数,
分析:如果已知dp[i][j],如果s[i+1]==s[j+1],dp[i+1][j+1]=dp[i][j],否则,dp[i+1][j+1]=min(dp[i+1][j],dp[i][j+1])+1。

主要的思路是先初始化长度为1的子串,例如:dp[0][0]=0,dp[1][1]=0,dp[2][2]=0.....dp[n-1][n-1]=0;
然后通过长度为1的dp值计算长度为2的子串,dp[0][1],dp[1][2],dp[2][3]....dp[n-2][n-1];一直推到长度为n,这时候dp[0][n-1]的值就是答案。所以一共需要两个循环,外层循环是长度,内层循环是下标位置。

代码:

#include
#include
#include
using namespace std;
string s;
int n;
int dp[1000][1000];
int main()
{
	cin >> s;
	n = s.length();
	for (int i = 0; i < n; i++)
	{
		dp[i][i] = 0;
		if (s[i] == s[i + 1]&&i+1
这里就是这两种方法啦,还有一种方法是递归~(自己琢磨),emmmm,有问题戳我哦,么么哒

你可能感兴趣的:(动态规划,dp,回)