Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Length of longest common subsequence of lists

Is there a built-in function in python which returns a length of longest common subsequence of two lists?

a=[1,2,6,5,4,8]
b=[2,1,6,5,4,4]

print a.llcs(b)

>>> 3

I tried to find longest common subsequence and then get length of it but I think there must be a better solution.

like image 826
Milano Avatar asked Jul 03 '14 07:07

Milano


People also ask

What is the length of the longest common subsequence?

What is the length of the longest common subsequence? Explanation: The longest common subsequence is “PRTPQRS” and its length is 7.

How do you find the length of the longest subsequence?

The following steps are followed for finding the longest common subsequence. Create a table of dimension n+1*m+1 where n and m are the lengths of X and Y respectively. The first row and the first column are filled with zeros. Fill each cell of the table using the following logic.

How do I generate all subsequences of a string in Python?

A String is a subsequence of a given String, that is generated by deleting some character of a given string without changing its order. Recommended: Please try your approach on {IDE} first, before moving on to the solution. Using Pick and Don't Pick concept : Python3.


1 Answers

You can easily retool a LCS into a LLCS:

def lcs_length(a, b):
    table = [[0] * (len(b) + 1) for _ in xrange(len(a) + 1)]
    for i, ca in enumerate(a, 1):
        for j, cb in enumerate(b, 1):
            table[i][j] = (
                table[i - 1][j - 1] + 1 if ca == cb else
                max(table[i][j - 1], table[i - 1][j]))
    return table[-1][-1]

Demo:

>>> a=[1,2,6,5,4,8]
>>> b=[2,1,6,5,4,4]
>>> lcs_length(a, b)
4

If you wanted the longest common substring (a different, but related problem, where the subsequence is contiguous), use:

def lcsubstring_length(a, b):
    table = [[0] * (len(b) + 1) for _ in xrange(len(a) + 1)]
    l = 0
    for i, ca in enumerate(a, 1):
        for j, cb in enumerate(b, 1):
            if ca == cb:
                table[i][j] = table[i - 1][j - 1] + 1
                if table[i][j] > l:
                    l = table[i][j]
    return l

This is very similar to the lcs_length dynamic programming approach, but we track the maximum length found so far (since it is no longer guaranteed the last element in the table is the maximum).

This returns 3:

>>> lcsubstring_length(a, b)
3

A sparse table variant to not have to track all the 0s:

def lcsubstring_length(a, b):
    table = {}
    l = 0
    for i, ca in enumerate(a, 1):
        for j, cb in enumerate(b, 1):
            if ca == cb:
                table[i, j] = table.get((i - 1, j - 1), 0) + 1
                if table[i, j] > l:
                    l = table[i, j]
    return l
like image 64
Martijn Pieters Avatar answered Sep 22 '22 07:09

Martijn Pieters