HDU-1503(最长公共子序列+路径跟踪)

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

你可能感兴趣的:(HDU-1503)