HDU 1503 Advanced Fruits(LCS变形且输出解)
http://acm.hdu.edu.cn/showproblem.php?pid=1503
题意:
给你两个字符串s1和s2, 要你输出它们的并串s. 其中s1是s的一个子序列且s2也是s的一个子序列且s是所有符合前面要求的最短字符串.
分析:
令dp[i][j]==x表示s1串的前i个字符和s2串的前j个字符组成的串的LCS长度为x.
我们先求出LCS的dp数组值. 然后按照POJ2250:
http://blog.csdn.net/u013480600/article/details/40743953
类似的DFS过程即可输出s串.
大体的思想是:
假设dfs(i,j)表示要输出i个字符(从0计数)和j个字符的串的并.
如果i==0或j==0, 那么直接输出剩余的另一个串并return即可.
否者(下面3个过程保证i>0且j>0):
如果s[i-1]==s[j-1], 那么先dfs(i-1,j-1),再输出一次s1[i-1](第一个串的第i个字符)即可.
如果s[i-1]!=s[j-1]时:
如果dp[i-1][j]>dp[i][j-1], dfs(i-1,j), 再输出s1[i-1]即可.
如果dp[i-1][j]<=dp[i][j-1], dfs(i,j-1), 再输出s2[j-1]即可.
(仔细体会上述过程)
AC代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=100+5;
int n,m;
int dp[maxn][maxn];
char s1[maxn],s2[maxn];
void dfs(int i,int j)
{
if(i+j==0) return;
else if(i==0)//s1串已经输出完毕
{
for(int k=0;k<j;k++)
printf("%c",s2[k]);
return ;
}
else if(j==0)//s2串已经输出完毕
{
for(int k=0;k<i;k++)
printf("%c",s1[k]);
return ;
}
//下面的递归保证i>0且j>0.
if(s1[i-1]==s2[j-1]) dfs(i-1,j-1), printf("%c",s1[i-1]);
else if(dp[i-1][j]>dp[i][j-1]) dfs(i-1,j),printf("%c",s1[i-1]);
else dfs(i,j-1),printf("%c",s2[j-1]);
}
int main()
{
while(scanf("%s%s",s1,s2)==2)
{
//初始化
n=strlen(s1);
m=strlen(s2);
memset(dp,0,sizeof(dp));
//递推
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(s1[i-1]==s2[j-1])
dp[i][j]=dp[i-1][j-1]+1;
else
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
//dfs+输出
dfs(n,m);
printf("\n");
}
return 0;
}
HDU 1503 Advanced Fruits(LCS变形且输出解)
原文地址:http://blog.csdn.net/u013480600/article/details/40787403