UVA11404 - Palindromic Subsequence - 动态规划

本文探讨了一个算法问题,目标是在给定字符串中找到最少需要删除的字符数,以便使其成为回文串。通过倒序字符串并计算最长公共子序列(LCS),作者提出了一种有效的方法。尽管最初尝试使用C语言实现导致超时,最终采用string处理和SQL函数库中的min()函数解决了问题。详细介绍了算法步骤和解决过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这道题思路是找最少去掉几个字符可以构成回文,那么就可以倒序之后求LCS,注意,只需要前半部分的LCS就可以了,后半部分不一定符合

因为前半部分一定是和倒序后的字符的前半部分的某些元素对应,那么实际上LCS之后的后半部分应该被回文串覆盖,也就是原串的前半部分对应的覆盖掉,但是求LCS时并没覆盖,所以只需要前半部分就可以了

这道题本来想用C做,但是超时了,无奈之下只能用string来处理,用SQL函数库中的min()来比较字典序了。无奈本人太渣,想不出怎么处理string。

AC代码:

#include<stdio.h>
#include<string.h>
#include<string>
using namespace std;
struct re
{
	string word;
	int len;
}dp[1005][1005];
int main()
{
	int i,j;
	char str1[1005],str2[1005];
	char a[1005],b[1005];
	while(scanf("%s",str1+1)!=EOF)
	{
		int t=strlen(str1+1);
		for(i=1;i<=t;i++)
		{
			str2[i]=str1[t-i+1];
		}
		for(i=0;i<=t;i++)
		{
			dp[0][i].len=0;
			dp[0][i].word="";
		}
		for(i=1;i<=t;i++)
		{
			for(j=1;j<=t;j++)
			{
				if(str1[i]==str2[j])
				{
					dp[i][j].len=dp[i-1][j-1].len+1;
					dp[i][j].word=dp[i-1][j-1].word+str1[i];
				}
				else
				{
					if(dp[i-1][j].len>dp[i][j-1].len)
					{
						dp[i][j].len=dp[i-1][j].len;
						dp[i][j].word=dp[i-1][j].word;
					}
					else if(dp[i-1][j].len<dp[i][j-1].len)
					{
						dp[i][j].len=dp[i][j-1].len;
						dp[i][j].word=dp[i][j-1].word;
					}
					else
					{
						dp[i][j].len=dp[i-1][j].len;
						dp[i][j].word=min(dp[i-1][j].word,dp[i][j-1].word);
					}
				}
			}
		}
		int l=dp[t][t].len;
		if(l%2==0)
		{
			for(int i=0;i<l/2;i++)
			{
				printf("%c",dp[t][t].word[i]);
			}
			for(int i=l/2-1;i>=0;i--)
			{
				printf("%c",dp[t][t].word[i]);
			}
			puts("");
		}
		else
		{
			for(int i=0;i<=l/2;i++)
			{
				printf("%c",dp[t][t].word[i]);
			}
			for(int i=l/2-1;i>=0;i--)
			{
				printf("%c",dp[t][t].word[i]);
			}
			puts("");
		}
	}
	return 0;
}

C的TLE代码,求大牛指点怎么改

#include<stdio.h>
#include<string.h>
struct re
{
	char word[1005];
	int len;
}dp[1005][1005];
char *dicmin(char *a,char *b)
{
	for(int i=0;i<=strlen(a)/2;i++)
	{
		if(a[i]-b[i]<0)
		{
			return a;
		}
		else if(a[i]-b[i]>0)
		{
			return b;
		}
	}
	return a;
}
int main()
{
	int i,j;
	char str1[1005],str2[1005];
	while(gets(str1+1))
	{
		int t=strlen(str1+1);
		for(i=1;i<=t;i++)
		{
			str2[i]=str1[t-i+1];
		}
		for(i=0;i<=t;i++)
		{
			dp[0][i].len=0;
			dp[0][i].word[0]=0;
		}
		for(i=1;i<=t;i++)
		{
			for(j=1;j<=t;j++)
			{
				if(str1[i]==str2[j])
				{
					dp[i][j].len=dp[i-1][j-1].len+1;
					strcpy(dp[i][j].word,dp[i-1][j-1].word);
					int l=strlen(dp[i][j].word);
					dp[i][j].word[l]=str1[i];
					dp[i][j].word[l+1]=0;
				}
				else
				{
					if(dp[i-1][j].len>dp[i][j-1].len)
					{
						dp[i][j].len=dp[i-1][j].len;
						strcpy(dp[i][j].word,dp[i-1][j].word);
					}
					else if(dp[i-1][j].len<dp[i][j-1].len)
					{
						dp[i][j].len=dp[i][j-1].len;
						strcpy(dp[i][j].word,dp[i][j-1].word);
					}
					else
					{
						dp[i][j].len=dp[i-1][j].len;
						strcpy(dp[i][j].word,dicmin(dp[i-1][j].word,dp[i][j-1].word));
					}
				}
			}
		}
		int l=strlen(dp[t][t].word);
		if(l%2==0)
		{
			for(int i=0;i<l/2;i++)
			{
				printf("%c",dp[t][t].word[i]);
			}
			for(int i=l/2-1;i>=0;i--)
			{
				printf("%c",dp[t][t].word[i]);
			}
			puts("");
		}
		else
		{
			for(int i=0;i<=l/2;i++)
			{
				printf("%c",dp[t][t].word[i]);
			}
			for(int i=l/2-1;i>=0;i--)
			{
				printf("%c",dp[t][t].word[i]);
			}
			puts("");
		}
	}
	return 0;
}


### 动态规划算法基本原理 动态规划是一种解决多阶段决策过程最优化问题的方法。它通过把原问题分解成相对简单的子问题的方式求解复杂问题。这种方法的核心在于存储已经计算过的中间状态的结果,从而避免重复计算。 #### 子问题重叠特性 动态规划依赖于子问题的重叠性质。这意味着一个问题可以被划分为多个更小的子问题,并且这些子问题会被多次调用[^3]。为了提高效率,动态规划会保存每一个子问题的解决方案,通常使用表格或者数组来记录这些结果。 #### 最优子结构 另一个重要的概念是最优子结构性质,即如果一个问题的最优解包含了其子问题的最优解,则该问题具有最优子结构属性。这一特点使得我们可以自底向上构建整个问题的最佳解答方案。 以下是基于上述理论的一个简单例子——寻找字符串中的最长回文子串: ```python def longest_palindromic_substring(s): n = len(s) if n == 0: return "" start, max_length = 0, 1 dp = [[False]*n for _ in range(n)] # Every single character is a palindrome of length 1. for i in range(n): dp[i][i] = True # Check substrings of length 2 to n. for end in range(1, n): for begin in range(end): if s[begin] == s[end]: if (end - begin <= 2 or dp[begin+1][end-1]): dp[begin][end] = True current_len = end - begin + 1 if current_len > max_length: max_length = current_len start = begin return s[start:start + max_length] print(longest_palindromic_substring("babad")) ``` 此代码片段展示了如何应用动态规划方法找到给定字符串内的最长回文子串[^2]。 #### 实现步骤概述 尽管这里不采用逐步描述方式,但仍需提及几个关键环节:定义状态转移方程、初始化边界条件以及最终结果提取逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值