Skip to content

Commit 737083f

Browse files
committed
add lcs problem to DP
1 parent a9bbf7c commit 737083f

File tree

8 files changed

+75
-16
lines changed

8 files changed

+75
-16
lines changed

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
10.13.0

docs/SUMMARY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
* [String Search](searching/string-matching.md)
4949
* [Dynamic Programming][dynamic]
5050
* [Overview][dynamic]
51+
* [Fibonacci Numbers](dynamic-programming/fibonacci-numbers.md)
52+
* [LCS problem](dynamic-programming/lcs-problem.md)
5153
* [Greedy Algorithms][greedy]
5254
* [Overview][greedy]
5355

docs/dynamic-programming/fibonacci-numbers.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,20 @@ FIBONACCI(n)
4646
</code>
4747
</pre>
4848

49-
Therefore, FIBONACCI(k) only takes **one** recursion, &forall; k &isin; n; and all memoized calls use &Theta;(1) time
49+
Therefore, FIBONACCI(k) only takes **one** recursion, &forall; k &isin; n; and all memoized calls use &Theta;(1) time. Thus, the time complexity is &Omicron;(n), space complexity is &Omicron;(1)
50+
51+
What about we don't want to have recursions? Then, we can use an extra linear space to store the FIB(n - 1) and FIB(n - 2) when computing FIB(n), which is to use _iteration_ in replacement of _recursion_ and having the same time complexity but avoid the use of recursion, which is also called **bottom-up DP**.
52+
53+
<pre>
54+
<code>
55+
FIBONACCI(n)
56+
fib := {}
57+
for k in 1...n
58+
if k &les; 2
59+
f = 1
60+
else
61+
f = fib[n - 1] + fib[n - 2]
62+
fib[k] = f
63+
return fib[n]
64+
</code>
65+
</pre>
Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,54 @@
11
# LCS (longest-common-subsequence) problem
22

3-
[longest-common-subsequence](https://en.wikipedia.org/wiki/Longest_common_subsequence_problem) differs from problem of finding the [longest common substring](https://en.wikipedia.org/wiki/Longest_common_substring_problem); and it has wide applications such as [diff utility](https://en.wikipedia.org/wiki/Diff_utility) and [bioinformatics](https://en.wikipedia.org/wiki/Bioinformatics)
3+
[longest-common-subsequence](https://en.wikipedia.org/wiki/Longest_common_subsequence_problem) differs from problem of finding the [longest common substring](https://en.wikipedia.org/wiki/Longest_common_substring_problem); and it has wide applications such as [diff utility](https://en.wikipedia.org/wiki/Diff_utility) and [bioinformatics](https://en.wikipedia.org/wiki/Bioinformatics).
4+
5+
The problem is formally defined as follows: define two strings for example _abcgf_ and _achfe_, find the same longest subsequence from both of them. A subsequence is composed of characters in same relative order within the string but not necessarily being contiguous. Strings like _ac_, _bc_, _bf_, _abf_ are all subsequences of string _abcgf_.
6+
7+
From all the subsequences of strings _abcgf_ and _achfe_, the common ones are _a_, _ac_, _cf_, _c_, _f_, _acf_, the longest common subsequence is _acf_.
8+
9+
## Analysis of this problem
10+
11+
Define two sequences X[0..m-1] and Y[0..n-1]. And L(X[0..m-1], Y[0..n-1]) be the LCS of the two sequences X and Y. LCS problem can be solved in dynamic programming for its satisfaction of two important factors:
12+
13+
- Optimal Substructure
14+
15+
If a problem has an optimal solution and its sub-problems also have optimal solutions, then we say this problem has optimal substructure.
16+
17+
In the above example, sequence X is _abcgf_ and sequence Y is _achfe_; Then, if the last characters of X and Y match we only need to find out if the preceding characters match: L(X[0..m-1], Y[0..n-1]) = 1 + L(X[0..m-2], Y[0..n-2]).
18+
19+
If the last characters of X and Y do not match, we need to find out the maximal LCS between L(X[0..m-2], Y[0..n-1]) and L(X[0..m-1], Y[0..n-2]).
20+
21+
- Overlapping Subproblems
22+
23+
In the recursion of finding common sequences, there are overlapping function calls; they are called overlapping subproblems:
24+
25+
In the above example, finding the LCS of X and Y is broken down into finding L(_abcgf_, _achf_) and L(_abcg_, _achfe_), the next level recursions of both have overlapping subproblems: L(_abcg_, _achf_). By memoization, the computing cost can be saved significantly (from exponential time to polynomial time).
26+
27+
Then, the following formula is given for this problem to be solved in dynamic programming:
28+
29+
<figure style="text-align: center">
30+
<img src="../images/lcs.png" />
31+
<figcaption>Figure 1. LCS Formula</figcaption>
32+
</figure>
33+
34+
## Pseudocode Solution
35+
36+
X of size m, Y of size n
37+
38+
```
39+
LCS(X, Y)
40+
initialize a 2-D array L of size m+1 by n+1
41+
42+
for i in m
43+
for j in n
44+
if i == 0 and j == 0
45+
L[i][j] = 0
46+
else if X[i - 1] == Y[j - 1]
47+
L[i][j] = 1 + L[i - 1][j - 1]
48+
else
49+
L[i][j] = max(L[i][j - 1], L[i - 1][j])
50+
51+
return L[m][n]
52+
```
53+
54+
The time and the space complexity are both &Omicron;(n &times; m).

docs/dynamic-programming/overview.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,13 @@ In contrast to the paradigm of [DnC][DnC] that sub-problems are independent, dyn
88

99
The typical [dynamic programming][dynamic] algorithm is developed in steps follow:
1010

11-
1. Characterize the _optimal_ sub-structures along with possible moves.
11+
1. Characterize the _optimal_ sub-structures along with possible moves. (think of it as finding a DAG for a solution path)
1212
2. Define the recurrence relations of sub-problems.
1313
3. Compute recursively or iteratively in a _bottom-up_ fashion or _top-down_ with [_memoization_](https://en.wikipedia.org/wiki/Memoization) fashion.
1414
4. Construct an overall _optimal_ solution or combining solutions of sub-problems.
1515

1616
_Noted that the word **programming** does not stand for **computer programming** but a tabulation method that was invented by [R. Bellman](https://en.wikipedia.org/wiki/Richard_E._Bellman)_.
1717

18-
## Principles of Dynamic Programming
19-
20-
21-
22-
## Classic Knapsack Problem
23-
2418
## Comparing with [Greedy Algorithms][greedy]
2519

2620
It is often confusing to determine if the programming logic is built on [dynamic programming][dynamic] or [greedy algorithms][greedy]. Both are adopted in favor of tackling _optimization problem_, and [dynamic programming][dynamic] seeks and combines the previous solutions for sub-problems to yield the final result while [greedy algorithms][greedy] chooses locally optimal solution in each run and not guarantee to have the optimal result.

docs/images/lcs.png

41.6 KB
Loading

docs/searching/hash-table.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,6 @@ Overall, a killer solution is by using the concept of [Hash Table][hash-table].
186186

187187
### Java 8 HashMap
188188

189-
> _reference_:
190-
> http://www.nagarro.com/de/perspectives/post/24/performance-improvement-for-hashmap-in-java-8
191-
192189
Hash collisions in hash table data structures have significant impact on performance of LOOKUP operation as to increase the [worst-case](../asymptotic-analysis.md) running time from &Omicron;(1) to &Omicron;(n).
193190

194191
To improve upon that, Java8 spec of HashMap implementations requires the buckets containing colliding keys should store entries in a balanced tree instead of linked list. Hence, the searching operation takes no more than &Omicron;(log(n)) in general.

docs/sorting/shell-sort.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@ In 1986, [Prof. Robert Sedgewick](https://en.wikipedia.org/wiki/Robert_Sedgewick
5656

5757
## Additional Resources
5858

59-
1. Computer Algorithms: Shell Sort, http://www.stoimen.com/blog/2012/02/27/computer-algorithms-shell-sort/
59+
1. Fastest gap sequence for shell sort? https://stackoverflow.com/questions/2539545/fastest-gap-sequence-for-shell-sort
6060

61-
2. Fastest gap sequence for shell sort? https://stackoverflow.com/questions/2539545/fastest-gap-sequence-for-shell-sort
62-
63-
3. Analysis of Shell Sort and Related Algorithms, R. Sedgewick, Princeton U. http://www.cs.princeton.edu/~rs/shell/paperF.pdf
61+
2. Analysis of Shell Sort and Related Algorithms, R. Sedgewick, Princeton U. http://www.cs.princeton.edu/~rs/shell/paperF.pdf

0 commit comments

Comments
 (0)