Skip to content

Commit 3c1d82d

Browse files
authored
Merge pull request #59 from BrianLusina/feat/dp-longest-common-subsequence
Dynamic Programming | Longest common subsequence
2 parents a34c257 + 74dba52 commit 3c1d82d

File tree

10 files changed

+98
-1
lines changed

10 files changed

+98
-1
lines changed

DIRECTORY.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
* [Test Letter Combination](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/backtracking/letter_combination/test_letter_combination.py)
1616
* Partition String
1717
* [Test Partition String](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/backtracking/partition_string/test_partition_string.py)
18+
* Permutations
19+
* Generate Permutations
20+
* [Test Generate Permutations](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/backtracking/permutations/generate_permutations/test_generate_permutations.py)
1821
* Bfs
1922
* Graphs
2023
* Dot Dsl
@@ -34,6 +37,8 @@
3437
* [Test House Robber](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/house_robber/test_house_robber.py)
3538
* Knapsack 01
3639
* [Test Knapsack 01](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/knapsack_01/test_knapsack_01.py)
40+
* Longest Common Subsequence
41+
* [Test Longest Common Subsequence](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/longest_common_subsequence/test_longest_common_subsequence.py)
3742
* Unique Paths
3843
* [Test Unique Paths](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/unique_paths/test_unique_paths.py)
3944
* Huffman
@@ -530,6 +535,8 @@
530535
* [Roman Numerals](https://github.com/BrianLusina/PythonSnips/blob/master/pyregex/roman_numerals.py)
531536

532537
## Pystrings
538+
* Balanced Paren
539+
* [Test Balanced Paren](https://github.com/BrianLusina/PythonSnips/blob/master/pystrings/balanced_paren/test_balanced_paren.py)
533540
* Domain Name
534541
* [Extract Host](https://github.com/BrianLusina/PythonSnips/blob/master/pystrings/domain_name/extract_host.py)
535542
* Greatest Common Divisor
@@ -859,7 +866,6 @@
859866
* [Test Ascii Converter](https://github.com/BrianLusina/PythonSnips/blob/master/tests/pystrings/test_ascii_converter.py)
860867
* [Test Autocomplete](https://github.com/BrianLusina/PythonSnips/blob/master/tests/pystrings/test_autocomplete.py)
861868
* [Test Backspaces](https://github.com/BrianLusina/PythonSnips/blob/master/tests/pystrings/test_backspaces.py)
862-
* [Test Balanced Paren](https://github.com/BrianLusina/PythonSnips/blob/master/tests/pystrings/test_balanced_paren.py)
863869
* [Test Bob](https://github.com/BrianLusina/PythonSnips/blob/master/tests/pystrings/test_bob.py)
864870
* [Test Caps Counter](https://github.com/BrianLusina/PythonSnips/blob/master/tests/pystrings/test_caps_counter.py)
865871
* [Test Character Counter](https://github.com/BrianLusina/PythonSnips/blob/master/tests/pystrings/test_character_counter.py)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Longest Common Subsequence
2+
3+
Given two strings text1 and text2, return the length of their longest common subsequence. If there is no common
4+
subsequence, return 0.
5+
6+
A subsequence of a string is a new string generated from the original string with some characters (can be none) deleted
7+
without changing the relative order of the remaining characters.
8+
9+
For example, "ace" is a subsequence of "abcde".
10+
A common subsequence of two strings is a subsequence that is common to both strings.
11+
12+
Example 1:
13+
14+
```text
15+
Input: text1 = "abcde", text2 = "ace"
16+
Output: 3
17+
Explanation: The longest common subsequence is "ace" and its length is 3.
18+
```
19+
20+
Example 2:
21+
22+
```text
23+
Input: text1 = "abc", text2 = "abc"
24+
Output: 3
25+
Explanation: The longest common subsequence is "abc" and its length is 3.
26+
```
27+
28+
Example 3:
29+
30+
```text
31+
Input: text1 = "abc", text2 = "def"
32+
Output: 0
33+
Explanation: There is no such common subsequence, so the result is 0.
34+
```
35+
36+
## Related Topics
37+
38+
- String
39+
- Dynamic Programming
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
def longest_common_subsequence(text1: str, text2: str) -> int:
2+
"""LCS is a classic problem. Let dp[i][j] be the LCS for string text1 ends at index i and string text2 ends at index
3+
j. If text1[i]==text2[j], then dp[i][j] would be 1+dp[i−1][j−1]. Otherwise, we target the largest LCS if we skip one
4+
character from either text1 or text2, i.e. dp[i][j]=max(dp[i−1][j],dp[i][j−1]).
5+
6+
Complexity:
7+
Where m is the length of text1 and n is the length of text2
8+
- Time complexity: O(m*n)
9+
- Space complexity: O(m*n)
10+
"""
11+
dp = [[0 for _ in range(len(text2) + 1)] for _ in range(len(text1) + 1)]
12+
13+
for i in range(len(text1) - 1, -1, -1):
14+
for j in range(len(text2) - 1, -1, -1):
15+
if text1[i] == text2[j]:
16+
dp[i][j] = 1 + dp[i + 1][j + 1]
17+
else:
18+
dp[i][j] = max(dp[i + 1][j], dp[i][j + 1])
19+
20+
return dp[0][0]
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import unittest
2+
from . import longest_common_subsequence
3+
4+
5+
class LongestCommonSubsequenceTestCase(unittest.TestCase):
6+
def test_abcde_ace_returns_3(self):
7+
"""should return 3 for text1='abcde' and text2='ace'"""
8+
text1 = 'abcde'
9+
text2 = 'ace'
10+
expected = 3
11+
actual = longest_common_subsequence(text1, text2)
12+
self.assertEqual(expected, actual)
13+
14+
def test_abc_abc_returns_3(self):
15+
"""should return 3 for text1='abc' and text2='abc'"""
16+
text1 = 'abc'
17+
text2 = 'abc'
18+
expected = 3
19+
actual = longest_common_subsequence(text1, text2)
20+
self.assertEqual(expected, actual)
21+
22+
def test_abc_def_returns_0(self):
23+
"""should return 0 for text1='abc' and text2='def'"""
24+
text1 = 'abc'
25+
text2 = 'def'
26+
expected = 0
27+
actual = longest_common_subsequence(text1, text2)
28+
self.assertEqual(expected, actual)
29+
30+
31+
if __name__ == '__main__':
32+
unittest.main()

0 commit comments

Comments
 (0)