码迷,mamicode.com
首页 > 其他好文 > 详细

0804------算法笔记----------最长公共子序列

时间:2014-08-05 03:00:08      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   使用   os   strong   io   for   

1.动态规划和子序列

  1.1 动态规划的特征:

    a)最优子结构,求问题的解必须获取子问题的最优解;

    b) 重叠子问题,使用原始的递归存在大量的重复计算。

  1.2 子序列的概念:

    a)子序列中的元素都是原字符串中的元素;

    b)子序列中元素的排列顺序,与他们在原字符串中的顺序相一致;

    c)子序列不同于子串,子序列中额元素在原字符串中未必是连续的。

    e)eg.src = "foobar" ,那么 "fbr" 就是一个子序列。

2.求最长公共子序列的三个版本

  2.1 最原始的递归求解,没有考虑重复计算问题。

#include <iostream>
#include <string>
using namespace std;

int LCS(const string &str1, const string &str2, int i, int j);

int main(int argc, const char *argv[])
{
    string str1 = "ABCBDAB";
    string str2 = "BDCABA";
    cout << LCS(str1, str2, str1.size(), str2.size()) << endl;

    return 0;
}

// i j 表示长度,即str1的前i个字节 和 str2的前j个字节
int LCS(const string &str1, const string &str2, int i, int j){
    if(i == 0 || j == 0)
        return 0;
    if(str1[i-1] == str2[j-1]){
        return LCS(str1, str2, i-1, j-1)+1;
    }
    else{
        int ret1 = LCS(str1, str2, i-1, j);
        int ret2 = LCS(str1, str2, i, j - 1);
        return  ret1 > ret2 ? ret1 : ret2 ;
    }
}

  2.2 画出上述递归树可以看到,大量的分支是重复的,那么重复的计算是否可以避免?显然可以,这里将所有的计算都存储在数组中,那么计算过的值就不会计算第二次,效率会大大提高。

#include <iostream>
#include <string>
#include <string.h>

using namespace std;

int memo[100][100];//全局数组 存储已经计算过的LCS[i][j]

int LCS(const string &str1, const string &str2, int i, int j);

int main(int argc, const char *argv[])
{
    string str1 = "ABCBDAB";
    string str2 = "BDCABA";
    memset(memo, -1, sizeof memo);
    cout << LCS(str1, str2, str1.size(), str2.size()) << endl;

    return 0;
}


// i j 表示长度,即str1的前i个字节 和 str2的前j个字节
int LCS(const string &str1, const string &str2, int i, int j){
    if(memo[i][j] != -1)
        return memo[i][j];
    if(i == 0 || j == 0)
        return 0;
    if(str1[i-1] == str2[j-1]){
        memo[i][j] = LCS(str1, str2, i-1, j-1) + 1;
        return memo[i][j];
    }
    else{
        int ret1 = LCS(str1, str2, i-1, j);
        int ret2 = LCS(str1, str2, i, j - 1);
        memo[i][j] = ret1 > ret2 ? ret1 : ret2;
        return memo[i][j];
    }
}

  2.3 非递归方法。从串长度为 0 开始依次求解,这里可作图研究,执行的过程就是填充一个二维数组的过程。

#include <iostream>
#include <string>
#include <stdlib.h>
#include <string.h>
using namespace std;
/*
 * 最长公共子串
 */


int main(int argc, const char *argv[])
{
    if(argc != 3){
       cout << "Too Few Arguments" << endl;
       exit(EXIT_FAILURE);
    }
    string str1 = argv[1];
    string str2 = argv[2];
    int memo[100][100];
    memset(memo, -1, sizeof memo);
    int i, j;
    for(i = 0; i <= str1.size(); i++)
        for(j = 0; j <= str2.size(); j++){
            if(i == 0 | j == 0)
                memo[i][j] = 0;
            else{
                if(str1[i-1] == str2[j-1])
                    memo[i][j] = memo[i-1][j-1] + 1;
                else
                    memo[i][j] = memo[i-1][j] > memo[i][i-1] ? memo[i-1][j] : memo[i][j-1];
            }
        }
    cout << memo[str1.size()][str2.size()] << endl;

    return 0;
}

  

 

0804------算法笔记----------最长公共子序列,布布扣,bubuko.com

0804------算法笔记----------最长公共子序列

标签:style   blog   color   使用   os   strong   io   for   

原文地址:http://www.cnblogs.com/monicalee/p/3891349.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!