Skip to content

Commit c0e5404

Browse files
psalqvistPhilip Salqvist
andauthored
feat: add dynamic programming algorithm to strings.min_distance.py (keon#838)
also added a small unit test to ensure the algorithm is correct fixes: keon#15 Co-authored-by: Philip Salqvist <philipsalqvist@MacBook-Pro-som-tillhor-Philip.local>
1 parent 51f93c6 commit c0e5404

File tree

2 files changed

+48
-6
lines changed

2 files changed

+48
-6
lines changed

algorithms/strings/min_distance.py

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,51 @@
1212
"""
1313

1414
def min_distance(word1, word2):
15+
"""
16+
Finds minimum distance by getting longest common subsequence
17+
18+
:type word1: str
19+
:type word2: str
20+
:rtype: int
21+
"""
1522
return len(word1) + len(word2) - 2 * lcs(word1, word2, len(word1), len(word2))
1623

17-
def lcs(s1, s2, i, j):
24+
def lcs(word1, word2, i, j):
1825
"""
19-
The length of longest common subsequence among the two given strings s1 and s2
26+
The length of longest common subsequence among the two given strings word1 and word2
2027
"""
2128
if i == 0 or j == 0:
2229
return 0
23-
elif s1[i - 1] == s2[j - 1]:
24-
return 1 + lcs(s1, s2, i - 1, j - 1)
30+
if word1[i - 1] == word2[j - 1]:
31+
return 1 + lcs(word1, word2, i - 1, j - 1)
32+
return max(lcs(word1, word2, i - 1, j), lcs(word1, word2, i, j - 1))
33+
34+
def min_distance_dp(word1, word2):
35+
"""
36+
Finds minimum distance in a dynamic programming manner
37+
TC: O(length1*length2), SC: O(length1*length2)
38+
39+
:type word1: str
40+
:type word2: str
41+
:rtype: int
42+
"""
43+
length1, length2 = len(word1)+1, len(word2)+1
44+
res = [[0 for _ in range(length2)] for _ in range(length1)]
45+
46+
if length1 == length2:
47+
for i in range(1, length1):
48+
res[i][0], res[0][i] = i, i
2549
else:
26-
return max(lcs(s1, s2, i - 1, j), lcs(s1, s2, i, j - 1))
50+
for i in range(length1):
51+
res[i][0] = i
52+
for i in range(length2):
53+
res[0][i] = i
54+
55+
for i in range(1, length1):
56+
for j in range(1, length2):
57+
if word1[i-1] == word2[j-1]:
58+
res[i][j] = res[i-1][j-1]
59+
else:
60+
res[i][j] = min(res[i-1][j], res[i][j-1]) + 1
2761

28-
# TODO: Using dynamic programming
62+
return res[len(word1)][len(word2)]

tests/test_strings.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
repeat_string,
3333
text_justification,
3434
min_distance,
35+
min_distance_dp,
3536
longest_common_prefix_v1, longest_common_prefix_v2,
3637
longest_common_prefix_v3,
3738
rotate, rotate_alt,
@@ -535,6 +536,13 @@ class TestMinDistance(unittest.TestCase):
535536
def test_min_distance(self):
536537
self.assertEqual(2, min_distance("sea", "eat"))
537538
self.assertEqual(6, min_distance("abAlgocrithmf", "Algorithmmd"))
539+
self.assertEqual(4, min_distance("acbbd", "aabcd"))
540+
541+
class TestMinDistanceDP(unittest.TestCase):
542+
def test_min_distance(self):
543+
self.assertEqual(2, min_distance_dp("sea", "eat"))
544+
self.assertEqual(6, min_distance_dp("abAlgocrithmf", "Algorithmmd"))
545+
self.assertEqual(4, min_distance("acbbd", "aabcd"))
538546

539547

540548
class TestLongestCommonPrefix(unittest.TestCase):

0 commit comments

Comments
 (0)