http://acm.hdu.edu.cn/showproblem.php?pid=1503
解题思路:这道题就是给你两个单词,然后你要把两个单词拼接成一个新单词,使得新单词的子序列中包含两个单词,并且要使这个新单词最短。所以这道题就是求最长公共子序列,并且要记录下子序列的字母,以及他们在主串和副串中的原始位置,之后进行拼接输出。
int Max(int x,int y)
{
return x>y?x:y;
}
struct rem
{
int i,j;/*i记录主串位置,j记录副串当前字符位置*/
char ch;/*记录当前字符*/
};
char a[size],b[size];
int dp[size][size];
rem ans[size];
int len;/*指示ans的长度*/
void lcs(int m,int n)
{
int i,j;
memset(dp,0,sizeof(dp));
len = 0;
for (i=1;i<=m;i++)
{
for (j=1;j<=n;j++)
{
if(a[i]==b[j])
dp[i][j] = dp[i-1][j-1]+1;
else
dp[i][j] = Max(dp[i-1][j],dp[i][j-1]);
}
}
if(dp[m][n] == 0)/*如果没有公共序列,直接输出*/
printf("%s%s",a,b);
else
{
/*取出最长公共子序列的字母*/
i = m,j = n;
while (i!=0&&j!=0)
{
if ((dp[i][j] = dp[i-1][j-1]+1)&&a[i] == b[j])
{
ans[len].i = i;
ans[len].j = j;
ans[len++].ch = a[i];/*倒序保存最长公共子序列字母*/
i--,j--;
}
else if(dp[i-1][j]>dp[i][j-1])
i--;
else
j--;
}
/*取出最长公共子序列的字母*/
}
}
int main()
{
int a1,b1,i,j,k;
while (scanf("%s%s",a+1,b+1)!=EOF)
{
a1 = strlen(a+1);
b1 = strlen(b+1);
lcs(a1,b1);
i = j = 1;
for (k=len-1;k>=0;k--)
{
while (i!=ans[k].i)
{
printf("%c",a[i]);
i++;
}
while (j!=ans[k].j)
{
printf("%c",b[j]);
j++;
}
printf("%c",ans[k].ch);
i++,j++;
}
printf("%s%s/n",a+ans[0].i+1,b+ans[0].j+1);
}
return 0;
}