Smiley face

Peng et al. Algorithm_MLCS(Sparse Dynamic Programming, 2010)


Main features
Abstract of the paper [Peng 2010]

Detecting the interleaving relationship between sequences has become impor- tant because of its wide applications to genomic and signal comparison. Given a target sequence T and two merging sequences A and B, recently Huang et al. propose algo- rithms for the merged LCS problem, without or with block constraint, whose aim is to find the longest common subsequence (LCS) with interleaving relationship. Without block constraint, Huang’s algorithm requires O(nmr)-time and O(mr)-space, where n = |T|, m and r denote the longer and shorter length of A and B, respectively. In this paper, for solving the problem without block constraint, we first propose an algorithm with O(Lnr) time and O(m + Lr) space. We also propose an algorithm to solve the problem with block constraint. Our algorithms are more efficient than previous results, especially for sequences over large alphabets.

C++ source code
int MLCS_PengSparse(vector< int> T, vector< int> A, vector< int>B, int Tlen, int Alen, int Blen, int size)
{
    vector< vector< int>> nextA(size + 1, vector< int>(Alen + 1, 0));
    vector< vector< int>> nextB(size + 1, vector< int>(Blen + 1, 0));
    int len = 1;
    vector< vector< triple>> QL1(Tlen + 2, vector< triple>());
    vector< vector< triple>> QL2(Tlen + 2, vector< triple>());
    vector< vector< triple>> tempQL(Tlen + 2, vector< triple>());
    int qlsize = 0;
    int locationA = 0;
    int locationB = 0;
    //construct array of nextA
    for (int i = 1; i <= size; ++i) {
        locationA = Alen + 1;
        for (int j = Alen; j > 0; --j) {
            if (j == Alen)
                nextA[i][j] = locationA;
            if (A[j] == i) {
                locationA = j;
                nextA[i][j - 1] = locationA;
            }
            else {
                nextA[i][j - 1] = locationA;
            }
        }
    }

    //construct array of nextB
    for (int i = 1; i <= size; ++i) {
        locationB = Blen + 1;
        for (int j = Blen; j > 0; --j) {
            if (j == Blen)
                nextB[i][j] = locationB;
            if (B[j] == i) {
                locationB = j;
                nextB[i][j - 1] = locationB;
            }
            else {
                nextB[i][j - 1] = locationB;
            }
        }
    }


    int PosA = 0;
    int PosB = 0;
    int layer = 1;
    while (1) {
        if (layer % 2 == 1) {
            QL1[0].push_back(triple(0, 0));
            for (int l = 1; l <= len; l++)
            {
                for (auto mytriple = QL2[l - 1].begin(); mytriple != QL2[l - 1].end(); ++mytriple)
                {
                    PosA = nextA[T[layer - 1]][mytriple->x];
                    PosB = nextB[T[layer - 1]][mytriple->y];
                    if (PosA <= Alen) {
                        QL1[l].push_back(triple(PosA, mytriple->y));
                    }
                    if (PosB <= Blen) {
                        QL1[l].push_back(triple(mytriple->x, PosB));
                    }
                }
                if (QL2[l].size() > 0) {
                    for (auto mytriple = QL2[l].begin(); mytriple != QL2[l].end(); ++mytriple)
                    {
                        QL1[l].push_back(triple(mytriple->x, mytriple->y));
                    }
                }

                //2-D minima algorithm
                qlsize = QL1[l].size();
                if (qlsize > 1) {
                    for (int i = 0; i < qlsize; ++i) {
                        triple temptri = QL1[l][i];
                        if (!tempQL[temptri.x].empty() && temptri.y < tempQL[temptri.x][0].y) {
                            tempQL[temptri.x].erase(tempQL[temptri.x].begin());
                            tempQL[temptri.x].push_back(temptri);
                        }
                        else if (tempQL[temptri.x].empty() == true) {
                            tempQL[temptri.x].push_back(temptri);
                        }
                    }
                    QL1[l].clear();
                    int prevMaxY = Blen + 1;
                    for (int i = 0; i <= Alen; ++i) {
                        if (!tempQL[i].empty()) {
                            if (tempQL[i][0].y < prevMaxY) {
                                prevMaxY = tempQL[i][0].y;
                                QL1[l].push_back(tempQL[i][0]);
                            }
                            tempQL[i].clear();
                        }
                    }
                }
            }//end for j
            if (QL1[len].size() > 0)
                len++;
            if (layer == Tlen + 1)
                break;
            ++layer;
        }
        else {
            QL2[0].push_back(triple(0, 0));
            for (int l = 1; l <= len; l++)
            {
                for (auto mytriple = QL1[l - 1].begin(); mytriple != QL1[l - 1].end(); ++mytriple)
                {
                    PosA = nextA[T[layer - 1]][mytriple->x];
                    PosB = nextB[T[layer - 1]][mytriple->y];
                    if (PosA <= Alen) {
                        QL2[l].push_back(triple(PosA, mytriple->y));
                    }
                    if (PosB <= Blen) {
                        QL2[l].push_back(triple(mytriple->x, PosB));
                    }
                }
                if (QL1[l].size() > 0) {
                    for (auto mytriple = QL1[l].begin(); mytriple != QL1[l].end(); ++mytriple)
                    {
                        QL2[l].push_back(triple(mytriple->x, mytriple->y));
                    }
                }

                //2-D minima algorithm
                qlsize = QL2[l].size();
                if (qlsize > 1) {
                    for (int i = 0; i < qlsize; ++i) {
                        triple temptri = QL2[l][i];
                        if (!tempQL[temptri.x].empty() && temptri.y < tempQL[temptri.x][0].y) {
                            tempQL[temptri.x].erase(tempQL[temptri.x].begin());
                            tempQL[temptri.x].push_back(temptri);
                        }
                        else if (tempQL[temptri.x].empty() == true) {
                            tempQL[temptri.x].push_back(temptri);
                        }
                    }
                    QL2[l].clear();
                    int prevMaxY = Blen + 1;
                    for (int i = 0; i <= Alen; ++i) {
                        if (!tempQL[i].empty()) {
                            if (tempQL[i][0].y < prevMaxY) {
                                prevMaxY = tempQL[i][0].y;
                                QL2[l].push_back(tempQL[i][0]);
                            }
                            tempQL[i].clear();
                        }
                    }
                }
            }//end for j
            if (QL2[len].size() > 0)
                len++;
            if (layer == Tlen + 1)
                break;
            ++layer;
        }
    }

    return len - 1;
}
The files
  All_MLCS.cpp

Reference
Peng, Y.-H., Yang, C.-B., Huang, K.-S., Tseng, C.-T., Hor, C.-Y., 2010. Efficient sparse dynamic programming for the merged LCS problem with block constraints. International Journal of Innovative Computing, Information and Control 6, 1935–1947.