题意是给你两个单词 ch1、ch2 让你拼成一个单词ch ,ch1 和ch2 分别都是ch的子序列。并要求ch的长度最小 ,输出ch。
根据LCS原理 ,先找出最长公共子序列,对其转移的路线进行记录,然后用递归输出。
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
char ch1[110],ch2[110];
int dp[110][110];
int pre[110][110];
//输出
void lcs(int x,int y)
{
//到0,0时跳出
if(x==0&&y==0)return;
if(pre[x][y]==1){lcs(x,y-1);printf("%c",ch2[y]);}//若状态为1 则往左走输ch2
else if(pre[x][y]==3){lcs(x-1,y);printf("%c", ch1[x]);}//若状态为3,则往上走 输出ch1
else {lcs(x-1,y-1);printf("%c",ch1[x]);}//状态为2,则表明当前的ch1[x],ch2[y]是相等的 随便输出一个就可以。
}
int main()
{
freopen("in.in","r",stdin);
while(scanf("%s %s",ch1,ch2)!=EOF)
{
int len1 ,len2;
len1=strlen(ch1);
len2=strlen(ch2);
memset(dp,0,sizeof(dp));
memset(pre,0,sizeof(pre));
for(int i=len1;i>0;i--) ch1[i]=ch1[i-1];
for(int i=len2;i>0;i--) ch2[i]=ch2[i-1];
for(int l=0;l<=len1;l++) {pre[l][0]=3;}
for(int l=0;l<=len2;l++) {pre[0][l]=1;}
for(int i=1;i<=len1;i++)
{
for(int j=1;j<=len2;j++)
{
if(ch1[i]==ch2[j]) {dp[i][j]=dp[i-1][j-1]+1;pre[i][j]=2;}
else if(dp[i-1][j]<dp[i][j-1]) {dp[i][j]=dp[i][j-1];pre[i][j]=1;}
else {dp[i][j]=dp[i-1][j];pre[i][j]=3;}
}
}
lcs(len1,len2);
printf("\n");
memset(ch1,'\0',sizeof(ch1));
memset(ch2,'\0',sizeof(ch2));
}
return 0;
}