UVA11404 - Palindromic Subsequence - 动态规划

这道题思路是找最少去掉几个字符可以构成回文,那么就可以倒序之后求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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值