LCS,最长公共子序列

一个字符串S,去掉零个或者多个元素所剩下的子串称为S的子序列。最长公共子序列就是寻找两个给定序列的子序列,该子序列在两个序列中以相同的顺序出现,但是不必要是连续的。

例如序列X=ABCBDAB,Y=BDCABA。序列BCA是X和Y的一个公共子序列,但是不是X和Y的最长公共子序列,子序列BCBA是X和Y的一个LCS,序列BDAB也是。

暴力解法

寻找LCS的一种方法是枚举X所有的子序列,然后注意检查是否是Y的子序列,并随时记录发现的最长子序列。假设X有m个元素,则X有2^m个子序列,指数级的时间,对长序列不实际。

动态规划

使用动态规划求解这个问题,先寻找最优子结构。

LCS,最长公共子序列_第1张图片


#include
#include
#include
#include

using namespace std;

int LCS(const string& a, const string& b) //递归
{
    if (a.empty() || b.empty())
        return 0;
    if (a[0] == b[0])
        return LCS(a.substr(1), b.substr(1)) + 1;
    else
        return max(LCS(a.substr(1), b), LCS(a, b.substr(1)));
}

void LCS(const string& a, const string& b)//DP解法
{
    int aSize = a.size();
    int bSize = b.size();

    vector<vector<int>> v(aSize + 1, vector<int>(bSize + 1, 0));
    for (int i = 1; i < aSize + 1; i++)
    {
        for (int j = 1; j < bSize + 1; j++)
        {
            if (a[i - 1] == b[j - 1])
            {
                v[i][j] = v[i - 1][j - 1] + 1;
            }
            else
            {
                v[i][j] = max(v[i][j - 1], v[i - 1][j]);
            }
        }
    }
    cout << v[aSize][bSize] << endl;

    //根据表回溯出最长公共子序列,注意由于最长公共子序列可能不止一个,在这里只打印一个
    string output = "";
    int i = aSize - 1;
    int j = bSize - 1;
    while (i > 0 || j > 0)
    {
        if (a[i - 1] == b[j - 1])
        {
            output += a[i - 1];
            i--;
            j--;
        }
        else
        {
            if (v[i - 1][j] < v[i][j - 1])
            {
                j--;
            }
            else
            {
                i--;
            }
        }
    }
    reverse(output.begin(), output.end());
    cout << output << endl;
}


int main()
{

    LCS("hello", "hxlolll");
    return 0;
}

你可能感兴趣的:(数据结构,LCS,动态规划)