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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy