hdu 1503 Advanced Fruits(最长公共子序列变形)

http://acm.hdu.edu.cn/showproblem.php?pid=1503

题意:给两个字符串,组成一个长度尽可能小的字符串,它包含上述两个字符串,且原字符串中的字符在该串中的相对位置不变。

思路:想到了最长公共子序列,但需要找到最长公共子序列是哪些。可以拿个二维数组记录第一个字符串i和第二个字符串j处的状态。然后根据状态递归,分别用一个数组记录公共字符在两个字符串中的位置。这样就找到了最长公共子序列中的字符。

然后按要求输出。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

char s1[110],s2[110],s[210];
int pre[110][110];//pre[i][j]记录到达第一个字符串i与第二个字符串j的状态。
int len1,len2;
int dp[110][110];
int ind1[110],ind2[110];//记录公共字符在两字符串中的位置
int cnt;//记录公共子序列中字符的个数

//求最长公共子序列,并记录状态
void get_len()
{
	memset(dp,0,sizeof(dp));
	for(int i = 1; i <= len1; i++)
	{
		for(int j = 1; j <= len2; j++)
		{
			if(s1[i-1] == s2[j-1])
			{
				dp[i][j] = dp[i-1][j-1]+1;
				pre[i][j] = 0;
			}
			else
			{
				if(dp[i-1][j] > dp[i][j-1])
				{
					pre[i][j] = 1;
					dp[i][j] = dp[i-1][j];
				}
				else
				{
					pre[i][j] = 2;
					dp[i][j] = dp[i][j-1];
				}
			}
		}
	}

}
//递归查找公共子序列中每个字符在两字符串中所对应下标
void dfs(int i, int j)
{
	if(i == 0 || j == 0) return;
	if(pre[i][j] == 1)
		dfs(i-1,j);
	else if(pre[i][j] == 2)
		dfs(i,j-1);
	else
	{
		dfs(i-1,j-1);
		ind1[++cnt] = i-1;
		ind2[cnt] = j-1;
	}

}

int main()
{
	while(~scanf("%s %s",s1,s2))
	{
		len1 = strlen(s1);
		len2 = strlen(s2);
		get_len();
		cnt = 0;
		dfs(len1,len2);
		int count = 0;
		int j = 0,k = 0;
	
		for(int i = 1; i <= cnt; i++)
		{//将公共字符之前的字符存在s中
			for(; j <= ind1[i]-1; j++)
				s[count++] = s1[j];
			for(; k <= ind2[i]-1; k++)
				s[count++] = s2[k];
			s[count++] = s1[j];
			j++;
			k++;
		}

		while(s1[j] != '\0')
			s[count++] = s1[j++];
		while(s2[k] != '\0')
			s[count++] = s2[k++];
		s[count] = '\0';
		printf("%s\n",s);
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值