HDU 1503
两个水果组成一个新的水果
先求两个字符串的最长公共子序列,然后记录两个串中的最长公共子序列的坐标。然后依次输出最长公共子序列中两个水果串的内容。
例如:
peach pear
最长公共子序列为 pea
则输出就是 peachr 或者 pearch
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int MAXN=105;
int k;
int dp[MAXN][MAXN],path1[MAXN],path2[MAXN]; ///path1代表f1(第一种水果)最长公共子序列的路径 path2同path1
char f1[MAXN],f2[MAXN],fr[MAXN<<1]; ///用fr数组保存果
/* 将路径的起始位置设为水果串的结束点后一位 末尾位置设置为水果串的开始的前一位 方便后面保存结果 */
void LCS(){ ///求最长公共子序列(路径跟踪)
memset(dp,0,sizeof(dp));
for(int i=0;i<strlen(f1);i++){
for(int j=0;j<strlen(f2);j++){
if(f1[i]==f2[j]){
dp[i+1][j+1]=dp[i][j]+1;
}
else{
dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);
}
}
}
path1[0]=strlen(f1);
path2[0]=strlen(f2);
int i=strlen(f1);
int j=strlen(f2);
while(dp[i][j]){ ///记录路径部分
if(dp[i][j]==dp[i][j-1]){
j--;
}
else if(dp[i][j]==dp[i-1][j]){
i--;
}
else{
path1[k]=i-1;
path2[k++]=j-1;
i--; j--;
}
if(dp[i][j]==0){
path1[k]=-1;
path2[k++]=-1;
}
}
}
int main()
{
memset(f1,0,sizeof(f1));
memset(f2,0,sizeof(f2));
while(cin>>f1>>f2){
k=1;
memset(vis,false,sizeof(vis));
memset(fr,0,sizeof(fr));
LCS();
int Count=0;
for(int i=k-1;i>=0;i--){ ///保存结果 因为记录路径时是逆序 这点要注意
if(i!=k-1&&i!=0){
fr[Count++]=f1[path1[i]];
}
for(int j=path1[i]+1;j<path1[i-1];j++){
fr[Count++]=f1[j];
}
for(int j=path2[i]+1;j<path2[i-1];j++){
fr[Count++]=f2[j];
}
}
cout<<fr<<endl;
memset(f1,0,sizeof(f1));
memset(f2,0,sizeof(f2));
}
return 0;
}