diff --git a/algorithms/graph/centroid_decomposition.cpp b/algorithms/graph/centroid_decomposition.cpp
index 7cb5041607054ed0bbdde6894d67df1533c188dc..ba4d697c0f5f088cfa22630964e1ca7a3cff0c5a 100644
--- a/algorithms/graph/centroid_decomposition.cpp
+++ b/algorithms/graph/centroid_decomposition.cpp
@@ -1,15 +1,15 @@
 /// Centroid Decomposition
 ///
 /// Description:
-///   The Centroid Decomposition of a tree is a tree where its root is the
-/// centroid of the original tree, and its children are the centroid of each
+///   The Centroid Decomposition of a tree is a tree where: 1) its root is the
+/// centroid of the original tree, and 2) its children are the centroid of each
 /// tree resulting from the removal of the root from the original tree. \par
-///   The result is a tree with $lg(n)$ height, where the path from $a$ to $b$
-/// in the original tree can be decomposed into the path from a to lca($a$,$b$)
+///   The result is a tree with $\log n$ height, where the path from $a$ to $b$,
+/// in the original tree, can be decomposed into the path from a to lca($a$,$b$)
 /// and from lca($a$,$b$) to $b$. \par
 ///   This is useful because each one of the $n^2$ paths of the original tree
-/// is the concatenation of two paths in a set of $O(n lg(n))$ paths from a 
-/// node to all its ancestors in the centroid decomposition.
+/// is a concatenation of two paths in a set of $O(n \log n)$ paths (from each
+/// node to all of its ancestors in the centroid decomposition).
 ///
 /// Time: O(V log V)
 /// Space: O(V + E)
diff --git a/algorithms/paradigm/edit_distance.cpp b/algorithms/paradigm/edit_distance.cpp
index 71ff93cdef0506b4ce32b2a82645c2f216abedd2..1704de2736ad22ef8211292e0e1d0ccfed3169f6 100644
--- a/algorithms/paradigm/edit_distance.cpp
+++ b/algorithms/paradigm/edit_distance.cpp
@@ -3,12 +3,9 @@
 /// Time: O(m * n)
 /// Space: O(m * n)
 
-struct EditDistance {
-  vector<vector<int>> dp;
-
-  EditDistance(int N, int M) :
-    dp(N, vector<int>(M)) {}
+int dp[MAX][MAX];
 
+struct EditDistance {
   int run(string a, string b) {
     for (int i = 0; i <= a.size(); ++i)
       for (int j = 0; j <= b.size(); ++j)
diff --git a/algorithms/paradigm/longest_common_subsequence.cpp b/algorithms/paradigm/longest_common_subsequence.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e324fb170fdf7d0dbb865ea175eea30e5ca18186
--- /dev/null
+++ b/algorithms/paradigm/longest_common_subsequence.cpp
@@ -0,0 +1,40 @@
+/// Longest Common Subsequence
+///
+/// Time: O(n * m)
+/// Space: O(n * m)
+
+int dp[MAX][MAX];
+
+struct LCS {
+  string run(string a, string b) {
+    for (int i = 0; i <= a.size(); ++i) {
+      for (int j = 0; j <= b.size(); ++j) {
+        if (i == 0 || j == 0)
+          dp[i][j] = 0;
+        else if (a[i - 1] == b[j - 1])
+          dp[i][j] = dp[i - 1][j - 1] + 1;
+        else
+          dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
+      }
+    }
+
+    // The size is already at dp[n][m], now the common 
+    // subsequence is retrieved
+
+    int idx = dp[a.size()][b.size()];
+    string ans(idx, ' ');
+
+    int i = a.size(), j = b.size();
+    while (i > 0 && j > 0) {
+      if (a[i - 1] == b[ j - 1]) {
+        ans[idx - 1] = a[i - 1];
+        i--, j--, idx--;
+      } else if (dp[i - 1][j] > dp[i][j - 1]) 
+        i--;
+      else 
+        j--;
+    }
+
+    return ans;
+  }
+};
diff --git a/algorithms/structure/sqrt_decomposition.cpp b/algorithms/structure/sqrt_decomposition.cpp
index 69cfd43e7fd48768404251e550ab43ffb95faf9a..2defc34aa7ef7b0cfa44ceae21876f387b154104 100644
--- a/algorithms/structure/sqrt_decomposition.cpp
+++ b/algorithms/structure/sqrt_decomposition.cpp
@@ -2,7 +2,7 @@
 ///
 /// Time:
 ///   - preprocess: O(n)
-///   - query:      O(sqrt(n))
+///   - query:      O(sqrt{n})
 ///   - update:     O(1)
 /// Space: O(n)
 
diff --git a/caderno.pdf b/caderno.pdf
index 7fc0671ca628986b8ef7296abdaa30054a7e47e9..4b9d5207012eadeb183f0faa34051d31810dc47a 100644
Binary files a/caderno.pdf and b/caderno.pdf differ