#include

1006 最长公共子序列Lcs(输出路径)(51NOD基础题)

1006 最长公共子序列Lcs(51NOD基础题)

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题
 
给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的)。
比如两个串为:
 
abcicba
abdkscab
 
ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列。
Input
第1行:字符串A
第2行:字符串B
(A,B的长度 <= 1000)
Output
输出最长的子序列,如果有多个,随意输出1个。
Input示例
abcicba
abdkscab
Output示例
abca
/*

1006 最长公共子序列Lcs (输出最长公共子序列的具体路径 (不是长度))

思路:可以由  最长公共子序列长度  那道题目增加一条 递归 改编而来 

str1[l1-1] == str2[l2-1]   时  dp[l1][l2] = dp[l1-1][l2-1] + 1 ; 
str1[l1-1] != str2[l2-1]   时  dp[l1][l2] = max(dp[l1-1][l2] , dp[l1][l2-1]) ;  

*/

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std ;  
#define maxn 1000+5
int dp[maxn][maxn] ; 
int path[maxn][maxn] ; 
char str1[maxn] , str2[maxn] ; 

void printLCS(int L1 , int L2){
    if(L1 == 0 || L2 == 0 )//递归边界 
        return;
    
    if(path[L1][L2] == 3) {//str1[L1] == str2[L2] 
        printLCS(L1-1 , L2-1) ; 
        printf("%c" , str1[L1-1]) ; 
    } else if(path[L1][L2] == 1 ){
        printLCS(L1-1 , L2) ; 
    } else {
        printLCS(L1 , L2-1) ; 
    }
    return;
}

int main(){
    while(~scanf("%s %s" , str1 , str2)){
        memset(dp , 0 , sizeof(dp)) ; 
        memset(path , 0 , sizeof(path)) ; 
        int len1 = strlen(str1) ; 
        int len2 = strlen(str2) ; 
        for(int i=1 ; i<=len1 ; i++){
            for(int j=1 ; j<=len2 ; j++){// 编号的目的是  确定回溯方向 
                if(str1[i-1] == str2[j-1]){ // 编号为三的位置两个字符相同(需要输出) 
                    dp[i][j] = dp[i-1][j-1] + 1 ; 
                    path[i][j] = 3 ; 
                } else if(dp[i-1][j] > dp[i][j-1]){ 
                    path[i][j] = 1 ; 
                    dp[i][j] = dp[i-1][j] ; 
                } else {
                    path[i][j] = 2 ; 
                    dp[i][j] = dp[i][j-1] ; 
                }
            }
        }
        printLCS(len1 , len2 ) ; 
    }
    return 0 ; 
}

 

posted @ 2017-09-19 19:22  0一叶0知秋0  阅读(313)  评论(0编辑  收藏  举报