[Tutor] longest common substring

Andreas Perstinger andreas.perstinger at gmx.net
Sun Nov 13 23:28:45 CET 2011


On 2011-11-11 14:44, lina wrote:
> You are right, I did not think of this parts before. and actually the
> initiative wish was to find possible paths, I mean, possible
> substrings, all possible substrings. not the longest one, but at
> least bigger than 3.

I had some time today and since you have changed your initial task (from 
finding the longest common path to finding all common paths with a 
minimum length) I've modified the code and came up with the following 
solution:

def AllCommonPaths(list1, list2, minimum=3):
""" finds all common paths with a minimum length (default = 3)"""

     # First we have to initialize the necessary variables:
     # M is an empty table where we will store all found matches
     # (regardless of their length)

     M = [[0] * (len(list2)) for i in range(len(list1))]

     # length is a dictionary where we store the length of each common
     # path. The keys are the starting positions ot the paths in list1.

     length = {}

     # result will be a list of of all found paths

     result =[]

     # Now the hard work begins:
     # Each element of list1 is compared to each element in list2
     # (x is the index for list1, y is the index for list2).
     # If we find a match, we store the distance to the starting point
     # of the matching block. If we are in the left-most column (x == 0)
     # or in the upper-most row (y == 0) we have to set the starting
     # point ourself because we would get negative indexes if we look
     # for the predecessor cell (M[x - 1][y - 1]). Else, we are one
     # element farther away as the element before, so we add 1 to its
     # value.

     for x in range(len(list1)):
         for y in range(len(list2)):
             if list1[x] == list2[y]:
                 if (x == 0) or (y == 0):
                     M[x][y] = 1
                 else:
                     M[x][y] = M[x - 1][y - 1] + 1

     # To get everything done in one pass, we update the length of
     # the found path in our dictionary if it is longer than the minimum
     # length. Thus we don't have to get through the whole table a
     # second time to get all found paths with the minimum length (we
     # don't know yet if we are already at the end of the matching
     # block).

                 if M[x][y] >= minimum:
                     length[x + 1 - M[x][y]] = M[x][y]


     # We now have for all matching blocks their starting
     # position in list1 and their length. Now we cut out this parts
     # and create our resulting list

     for pos in length:
         result.append(list1[pos:pos + length[pos]])

     return result

I've tried to explain what I have done, but I'm sure you will still have 
questions :-).

Is this close to what you want?

Bye, Andreas

PS: Here's the function again without comments:

def AllCommonPaths(list1, list2, minimum=3):
     """ finds all common paths with a minimum length (default = 3)"""

     M = [[0] * (len(list2)) for i in range(len(list1))]
     length = {}
     result =[]

     for x in range(len(list1)):
         for y in range(len(list2)):
             if list1[x] == list2[y]:
                 if (x == 0) or (y == 0):
                     M[x][y] = 1
                 else:
                     M[x][y] = M[x - 1][y - 1] + 1
                 if M[x][y] >= minimum:
                     length[x + 1 - M[x][y]] = M[x][y]

     for pos in length:
         result.append(list1[pos:pos + length[pos]])

     return result


More information about the Tutor mailing list