-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathLCS.py
54 lines (43 loc) · 1.32 KB
/
LCS.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
"""LCS.py
Dynamic program for longest common subsequences
D. Eppstein, March 2002.
"""
import unittest
def LongestCommonSubsequence(A,B):
"""Find longest common subsequence of iterables A and B."""
A = list(A)
B = list(B)
# Fill dictionary lcsLen[i,j] with length of LCS of A[:i] and B[:j]
lcsLen = {}
for i in range(len(A)+1):
for j in range(len(B) + 1):
if i == 0 or j == 0:
lcsLen[i,j] = 0
elif A[i-1] == B[j-1]:
lcsLen[i,j] = lcsLen[i-1,j-1] + 1
else:
lcsLen[i,j] = max(lcsLen[i-1,j], lcsLen[i,j-1])
# Produce actual sequence by backtracking through pairs (i,j),
# using computed lcsLen values to guide backtracking
i = len(A)
j = len(B)
LCS = []
while lcsLen[i,j]:
while lcsLen[i,j] == lcsLen[i-1,j]:
i -= 1
while lcsLen[i,j] == lcsLen[i,j-1]:
j -= 1
i -= 1
j -= 1
LCS.append(A[i])
LCS.reverse()
return LCS
# If run standalone, perform unit tests
class LCSTest(unittest.TestCase):
def testLCS(self):
A = range(10)
B = reversed(A)
self.assertEqual(list(A),LongestCommonSubsequence(A,A))
self.assertEqual(len(LongestCommonSubsequence(A,B)),1)
if __name__ == "__main__":
unittest.main()