From b5f956c45e801203af0f2c7505988ac04cfd9453 Mon Sep 17 00:00:00 2001
From: BrianLusina <12752833+BrianLusina@users.noreply.github.com>
Date: Tue, 14 Nov 2023 06:09:48 +0300
Subject: [PATCH 1/3] feat(backtracking): permutations

---
 {pystrings => algorithms/backtracking}/permutations/__init__.py   | 0
 .../backtracking}/permutations/generate_permutations/README.md    | 0
 .../backtracking}/permutations/generate_permutations/__init__.py  | 0
 .../generate_permutations/test_generate_permutations.py           | 0
 .../permutations/lexicographic_permutations/README.md             | 0
 .../permutations/lexicographic_permutations/__init__.py           | 0
 6 files changed, 0 insertions(+), 0 deletions(-)
 rename {pystrings => algorithms/backtracking}/permutations/__init__.py (100%)
 rename {pystrings => algorithms/backtracking}/permutations/generate_permutations/README.md (100%)
 rename {pystrings => algorithms/backtracking}/permutations/generate_permutations/__init__.py (100%)
 rename {pystrings => algorithms/backtracking}/permutations/generate_permutations/test_generate_permutations.py (100%)
 rename {pystrings => algorithms/backtracking}/permutations/lexicographic_permutations/README.md (100%)
 rename {pystrings => algorithms/backtracking}/permutations/lexicographic_permutations/__init__.py (100%)

diff --git a/pystrings/permutations/__init__.py b/algorithms/backtracking/permutations/__init__.py
similarity index 100%
rename from pystrings/permutations/__init__.py
rename to algorithms/backtracking/permutations/__init__.py
diff --git a/pystrings/permutations/generate_permutations/README.md b/algorithms/backtracking/permutations/generate_permutations/README.md
similarity index 100%
rename from pystrings/permutations/generate_permutations/README.md
rename to algorithms/backtracking/permutations/generate_permutations/README.md
diff --git a/pystrings/permutations/generate_permutations/__init__.py b/algorithms/backtracking/permutations/generate_permutations/__init__.py
similarity index 100%
rename from pystrings/permutations/generate_permutations/__init__.py
rename to algorithms/backtracking/permutations/generate_permutations/__init__.py
diff --git a/pystrings/permutations/generate_permutations/test_generate_permutations.py b/algorithms/backtracking/permutations/generate_permutations/test_generate_permutations.py
similarity index 100%
rename from pystrings/permutations/generate_permutations/test_generate_permutations.py
rename to algorithms/backtracking/permutations/generate_permutations/test_generate_permutations.py
diff --git a/pystrings/permutations/lexicographic_permutations/README.md b/algorithms/backtracking/permutations/lexicographic_permutations/README.md
similarity index 100%
rename from pystrings/permutations/lexicographic_permutations/README.md
rename to algorithms/backtracking/permutations/lexicographic_permutations/README.md
diff --git a/pystrings/permutations/lexicographic_permutations/__init__.py b/algorithms/backtracking/permutations/lexicographic_permutations/__init__.py
similarity index 100%
rename from pystrings/permutations/lexicographic_permutations/__init__.py
rename to algorithms/backtracking/permutations/lexicographic_permutations/__init__.py

From 368dc20e823267893eeeda05fa9784df7e7454d8 Mon Sep 17 00:00:00 2001
From: BrianLusina <12752833+BrianLusina@users.noreply.github.com>
Date: Tue, 14 Nov 2023 06:41:23 +0300
Subject: [PATCH 2/3] feat(dp): longest common subsequence

---
 .../longest_common_subsequence/README.md      | 39 +++++++++++++++++++
 .../longest_common_subsequence/__init__.py    | 20 ++++++++++
 .../test_longest_common_subsequence.py        | 32 +++++++++++++++
 3 files changed, 91 insertions(+)
 create mode 100644 algorithms/dynamic_programming/longest_common_subsequence/README.md
 create mode 100644 algorithms/dynamic_programming/longest_common_subsequence/__init__.py
 create mode 100644 algorithms/dynamic_programming/longest_common_subsequence/test_longest_common_subsequence.py

diff --git a/algorithms/dynamic_programming/longest_common_subsequence/README.md b/algorithms/dynamic_programming/longest_common_subsequence/README.md
new file mode 100644
index 00000000..5171f8ee
--- /dev/null
+++ b/algorithms/dynamic_programming/longest_common_subsequence/README.md
@@ -0,0 +1,39 @@
+# Longest Common Subsequence
+
+Given two strings text1 and text2, return the length of their longest common subsequence. If there is no common
+subsequence, return 0.
+
+A subsequence of a string is a new string generated from the original string with some characters (can be none) deleted
+without changing the relative order of the remaining characters.
+
+For example, "ace" is a subsequence of "abcde".
+A common subsequence of two strings is a subsequence that is common to both strings.
+
+Example 1:
+
+```text
+Input: text1 = "abcde", text2 = "ace" 
+Output: 3  
+Explanation: The longest common subsequence is "ace" and its length is 3.
+```
+
+Example 2:
+
+```text
+Input: text1 = "abc", text2 = "abc"
+Output: 3
+Explanation: The longest common subsequence is "abc" and its length is 3.
+```
+
+Example 3:
+
+```text
+Input: text1 = "abc", text2 = "def"
+Output: 0
+Explanation: There is no such common subsequence, so the result is 0.
+```
+
+## Related Topics
+
+- String
+- Dynamic Programming
diff --git a/algorithms/dynamic_programming/longest_common_subsequence/__init__.py b/algorithms/dynamic_programming/longest_common_subsequence/__init__.py
new file mode 100644
index 00000000..be42b877
--- /dev/null
+++ b/algorithms/dynamic_programming/longest_common_subsequence/__init__.py
@@ -0,0 +1,20 @@
+def longest_common_subsequence(text1: str, text2: str) -> int:
+    """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
+    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
+    character from either text1 or text2, i.e. dp[i][j]=max(dp[i−1][j],dp[i][j−1]).
+
+    Complexity:
+    Where m is the length of text1 and n is the length of text2
+    - Time complexity: O(m*n)
+    - Space complexity: O(m*n)
+    """
+    dp = [[0 for _ in range(len(text2) + 1)] for _ in range(len(text1) + 1)]
+
+    for i in range(len(text1) - 1, -1, -1):
+        for j in range(len(text2) - 1, -1, -1):
+            if text1[i] == text2[j]:
+                dp[i][j] = 1 + dp[i + 1][j + 1]
+            else:
+                dp[i][j] = max(dp[i + 1][j], dp[i][j + 1])
+
+    return dp[0][0]
diff --git a/algorithms/dynamic_programming/longest_common_subsequence/test_longest_common_subsequence.py b/algorithms/dynamic_programming/longest_common_subsequence/test_longest_common_subsequence.py
new file mode 100644
index 00000000..eeeab261
--- /dev/null
+++ b/algorithms/dynamic_programming/longest_common_subsequence/test_longest_common_subsequence.py
@@ -0,0 +1,32 @@
+import unittest
+from . import longest_common_subsequence
+
+
+class LongestCommonSubsequenceTestCase(unittest.TestCase):
+    def test_abcde_ace_returns_3(self):
+        """should return 3 for text1='abcde' and text2='ace'"""
+        text1 = 'abcde'
+        text2 = 'ace'
+        expected = 3
+        actual = longest_common_subsequence(text1, text2)
+        self.assertEqual(expected, actual)
+
+    def test_abc_abc_returns_3(self):
+        """should return 3 for text1='abc' and text2='abc'"""
+        text1 = 'abc'
+        text2 = 'abc'
+        expected = 3
+        actual = longest_common_subsequence(text1, text2)
+        self.assertEqual(expected, actual)
+
+    def test_abc_def_returns_0(self):
+        """should return 0 for text1='abc' and text2='def'"""
+        text1 = 'abc'
+        text2 = 'def'
+        expected = 0
+        actual = longest_common_subsequence(text1, text2)
+        self.assertEqual(expected, actual)
+
+
+if __name__ == '__main__':
+    unittest.main()

From 74dba5200478c8cadac48c18254c37356688ac50 Mon Sep 17 00:00:00 2001
From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
Date: Tue, 14 Nov 2023 03:41:51 +0000
Subject: [PATCH 3/3] updating DIRECTORY.md

---
 DIRECTORY.md | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/DIRECTORY.md b/DIRECTORY.md
index 464f179a..f783f918 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -15,6 +15,9 @@
       * [Test Letter Combination](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/backtracking/letter_combination/test_letter_combination.py)
     * Partition String
       * [Test Partition String](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/backtracking/partition_string/test_partition_string.py)
+    * Permutations
+      * Generate Permutations
+        * [Test Generate Permutations](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/backtracking/permutations/generate_permutations/test_generate_permutations.py)
   * Bfs
     * Graphs
       * Dot Dsl
@@ -34,6 +37,8 @@
       * [Test House Robber](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/house_robber/test_house_robber.py)
     * Knapsack 01
       * [Test Knapsack 01](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/knapsack_01/test_knapsack_01.py)
+    * Longest Common Subsequence
+      * [Test Longest Common Subsequence](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/longest_common_subsequence/test_longest_common_subsequence.py)
     * Unique Paths
       * [Test Unique Paths](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/unique_paths/test_unique_paths.py)
   * Huffman
@@ -530,6 +535,8 @@
   * [Roman Numerals](https://github.com/BrianLusina/PythonSnips/blob/master/pyregex/roman_numerals.py)
 
 ## Pystrings
+  * Balanced Paren
+    * [Test Balanced Paren](https://github.com/BrianLusina/PythonSnips/blob/master/pystrings/balanced_paren/test_balanced_paren.py)
   * Domain Name
     * [Extract Host](https://github.com/BrianLusina/PythonSnips/blob/master/pystrings/domain_name/extract_host.py)
   * Greatest Common Divisor
@@ -859,7 +866,6 @@
     * [Test Ascii Converter](https://github.com/BrianLusina/PythonSnips/blob/master/tests/pystrings/test_ascii_converter.py)
     * [Test Autocomplete](https://github.com/BrianLusina/PythonSnips/blob/master/tests/pystrings/test_autocomplete.py)
     * [Test Backspaces](https://github.com/BrianLusina/PythonSnips/blob/master/tests/pystrings/test_backspaces.py)
-    * [Test Balanced Paren](https://github.com/BrianLusina/PythonSnips/blob/master/tests/pystrings/test_balanced_paren.py)
     * [Test Bob](https://github.com/BrianLusina/PythonSnips/blob/master/tests/pystrings/test_bob.py)
     * [Test Caps Counter](https://github.com/BrianLusina/PythonSnips/blob/master/tests/pystrings/test_caps_counter.py)
     * [Test Character Counter](https://github.com/BrianLusina/PythonSnips/blob/master/tests/pystrings/test_character_counter.py)