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; }