最長公共子序列LCS和最長子串SLCS

最長子序列LCS

#include <iostream>

using namespace std;

#define LEFT_UP 'a'
#define UP 'b'
#define LEFT 'c'
//求最長子序列長度
int Lcs_length(string s1, string s2, int* &num, char* &seq)
{

    int m = s1.length();
    int n = s2.length();
    int dim_1 = n + 1;
    for(int i = 0; i <= m; ++i)
    {
        *(num + i * dim_1 + 0) = 0;
    }
    for(int i = 0; i <= n; ++i)
    {
        *(num + 0 * dim_1 + i) = 0;
    }

    for(int i = 1; i <= m; ++i)
    {
        for(int j = 1; j <= n; ++j)
        {
            if(s1[i-1] == s2[j-1])
            {
                *(num + i * dim_1 + j) = *(num + (i-1) * dim_1 + j-1) + 1;
                *(seq + i * dim_1 + j) = LEFT_UP;
            }
            else if(*(num + (i-1) * dim_1 + j) >= *(num + i * dim_1 + j-1))
            {
                *(num + i * dim_1 + j) = *(num + (i-1) * dim_1 + j);
                *(seq + i * dim_1 + j) = UP;
            }
            else
            {
                *(num + i * dim_1 + j) = *(num + i * dim_1 + j-1);
                *(seq + i * dim_1 + j)= LEFT;
            }
        }
    }
    return *(num + m * dim_1 + n);
}

//輸出最長公共子序列
void Lcs(string s1, char* seq, int i, int j, int dim)
{
    if(i ==0 || j == 0)
    {
        return;
    }
    if(*(seq + i * dim + j) == LEFT_UP)
    {
        Lcs(s1, seq, i-1, j-1, dim);
        cout << s1[i-1];
    }
    else if(*(seq + i * dim + j) == UP)
    {
        Lcs(s1, seq, i-1, j, dim);
    }
    else
    {
        Lcs(s1, seq, i, j-1, dim);
    }
}
int main()
{
    string s1, s2;
    cin >> s1;
    cin >> s2;
    int* num = new int[(s1.length()+1)*(s2.length()+1)];  //保存當前最大子序列長度
    char* seq = new char[(s1.length()+1)*(s2.length()+1)];  //保存軌跡
    int len = Lcs_length(s1, s2, num, seq);

    cout << "longest length " << len << endl;

    //求最長公共子序列
    Lcs(s1, seq, s1.length(), s2.length(), s2.length()+1);
    return 0;
}

最長子串SLCS是特殊的LCS,因此只需要在LCS的基礎上稍作修改即可

#include <iostream>

using namespace std;

#define LEFT_UP 'a'
#define UP 'b'
#define LEFT 'c'

struct Pos //最長串的位置
{
    int i;
    int j;
}p1;

//求最長子序列長度
int Lcs_length(string s1, string s2, int* &num, char* &seq)
{

    int m = s1.length();
    int n = s2.length();
    int dim_1 = n + 1;
    int max_len = 0;
    for(int i = 0; i <= m; ++i)
    {
        *(num + i * dim_1 + 0) = 0;
    }
    for(int i = 0; i <= n; ++i)
    {
        *(num + 0 * dim_1 + i) = 0;
    }

    for(int i = 1; i <= m; ++i)
    {
        for(int j = 1; j <= n; ++j)
        {
            if(s1[i-1] == s2[j-1])
            {
                *(num + i * dim_1 + j) = *(num + (i-1) * dim_1 + j-1) + 1;
                if(*(num + i * dim_1 + j) > max_len)
                {
                    max_len = *(num + i * dim_1 + j);
                    p1.i = i;
                    p1.j = j;
                }
                *(seq + i * dim_1 + j) = LEFT_UP;
            }
            else
            {
                *(num + i * dim_1 + j) = 0;
                *(seq + i * dim_1 + j) = UP;
            }
        }
    }
    return max_len;
}

//求最長公共子序列
void Lcs(string s1, char* seq, int i, int j, int dim)
{
    if(i ==0 || j == 0)
    {
        return;
    }
    if(*(seq + i * dim + j) == LEFT_UP)
    {
        Lcs(s1, seq, i-1, j-1, dim);
        cout << s1[i-1];
    }
}
int main()
{
    string s1, s2;
    cin >> s1;
    cin >> s2;
    int* num = new int[(s1.length()+1)*(s2.length()+1)];  //保存當前最大子序列長度
    char* seq = new char[(s1.length()+1)*(s2.length()+1)];  //保存軌跡
    int len = Lcs_length(s1, s2, num, seq);

    cout << "longest length " << len << endl;

    //求最長公共子序列
    Lcs(s1, seq, p1.i, p1.j, s2.length()+1);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章