Update README.

This commit is contained in:
Oleksii Trekhleb 2018-04-26 08:08:13 +03:00
parent 01139e0b50
commit 15e798c130
5 changed files with 52 additions and 34 deletions

View File

@ -38,13 +38,13 @@
* [Power Set](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/power-set) - all subsets of the set * [Power Set](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/power-set) - all subsets of the set
* [Permutations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/permutations) (with and without repetitions) * [Permutations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/permutations) (with and without repetitions)
* [Combinations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/combinations) (with and without repetitions) * [Combinations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/combinations) (with and without repetitions)
* [FisherYates Shuffle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/fisher-yates) - random permutation of a finite sequence * [FisherYates Shuffle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/fisher-yates) - random permutation of a finite sequence
* [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequnce) (LCS)
* **String** * **String**
* [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences * [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences
* [Hamming Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/hamming-distance) - number of positions at which the symbols are different * [Hamming Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/hamming-distance) - number of positions at which the symbols are different
* [KnuthMorrisPratt Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/knuth-morris-pratt) - substring search * [KnuthMorrisPratt Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/knuth-morris-pratt) - substring search
* [Rabin Karp Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/rabin-karp) - substring search * [Rabin Karp Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/rabin-karp) - substring search
* [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-subsequnce) (LCS)
* [Longest Common Substring](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring) * [Longest Common Substring](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring)
* **Search** * **Search**
* [Binary Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search) * [Binary Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search)
@ -90,7 +90,7 @@
* **Dynamic Programming** * **Dynamic Programming**
* [Fibonacci Number](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fibonacci) * [Fibonacci Number](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fibonacci)
* [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences * [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences
* [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-subsequnce) (LCS) * [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequnce) (LCS)
* [Longest Common Substring](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring) * [Longest Common Substring](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring)
* Increasing subsequence * Increasing subsequence
* Longest Increasing subsequence * Longest Increasing subsequence

View File

@ -0,0 +1,31 @@
import longestCommonSubsequnce from '../longestCommonSubsequnce';
describe('longestCommonSubsequnce', () => {
it('should find longest common subsequence for two strings', () => {
expect(longestCommonSubsequnce([''], [''])).toEqual(['']);
expect(longestCommonSubsequnce([''], ['A', 'B', 'C'])).toEqual(['']);
expect(longestCommonSubsequnce(['A', 'B', 'C'], [''])).toEqual(['']);
expect(longestCommonSubsequnce(
['A', 'B', 'C'],
['D', 'E', 'F', 'G'],
)).toEqual(['']);
expect(longestCommonSubsequnce(
['A', 'B', 'C', 'D', 'G', 'H'],
['A', 'E', 'D', 'F', 'H', 'R'],
)).toEqual(['A', 'D', 'H']);
expect(longestCommonSubsequnce(
['A', 'G', 'G', 'T', 'A', 'B'],
['G', 'X', 'T', 'X', 'A', 'Y', 'B'],
)).toEqual(['G', 'T', 'A', 'B']);
expect(longestCommonSubsequnce(
['A', 'B', 'C', 'D', 'A', 'F'],
['A', 'C', 'B', 'C', 'F'],
)).toEqual(['A', 'B', 'C', 'F']);
});
});

View File

@ -1,26 +1,26 @@
/** /**
* @param {string} s1 * @param {string[]} set1
* @param {string} s2 * @param {string[]} set2
* @return {string} * @return {string[]}
*/ */
export default function longestCommonSubsequnce(s1, s2) { export default function longestCommonSubsequnce(set1, set2) {
// Init LCS matrix. // Init LCS matrix.
const lcsMatrix = Array(s2.length + 1).fill(null).map(() => Array(s1.length + 1).fill(null)); const lcsMatrix = Array(set2.length + 1).fill(null).map(() => Array(set1.length + 1).fill(null));
// Fill first row with zeros. // Fill first row with zeros.
for (let columnIndex = 0; columnIndex <= s1.length; columnIndex += 1) { for (let columnIndex = 0; columnIndex <= set1.length; columnIndex += 1) {
lcsMatrix[0][columnIndex] = 0; lcsMatrix[0][columnIndex] = 0;
} }
// Fill first column with zeros. // Fill first column with zeros.
for (let rowIndex = 0; rowIndex <= s2.length; rowIndex += 1) { for (let rowIndex = 0; rowIndex <= set2.length; rowIndex += 1) {
lcsMatrix[rowIndex][0] = 0; lcsMatrix[rowIndex][0] = 0;
} }
// Fill rest of the column that correspond to each of two strings. // Fill rest of the column that correspond to each of two strings.
for (let rowIndex = 1; rowIndex <= s2.length; rowIndex += 1) { for (let rowIndex = 1; rowIndex <= set2.length; rowIndex += 1) {
for (let columnIndex = 1; columnIndex <= s1.length; columnIndex += 1) { for (let columnIndex = 1; columnIndex <= set1.length; columnIndex += 1) {
if (s1[columnIndex - 1] === s2[rowIndex - 1]) { if (set1[columnIndex - 1] === set2[rowIndex - 1]) {
lcsMatrix[rowIndex][columnIndex] = lcsMatrix[rowIndex - 1][columnIndex - 1] + 1; lcsMatrix[rowIndex][columnIndex] = lcsMatrix[rowIndex - 1][columnIndex - 1] + 1;
} else { } else {
lcsMatrix[rowIndex][columnIndex] = Math.max( lcsMatrix[rowIndex][columnIndex] = Math.max(
@ -32,19 +32,19 @@ export default function longestCommonSubsequnce(s1, s2) {
} }
// Calculate LCS based on LCS matrix. // Calculate LCS based on LCS matrix.
if (!lcsMatrix[s2.length][s1.length]) { if (!lcsMatrix[set2.length][set1.length]) {
// If the length of largest common string is zero then return empty string. // If the length of largest common string is zero then return empty string.
return ''; return [''];
} }
let lcs = ''; const longestSequence = [];
let columnIndex = s1.length; let columnIndex = set1.length;
let rowIndex = s2.length; let rowIndex = set2.length;
while (columnIndex > 0 || rowIndex > 0) { while (columnIndex > 0 || rowIndex > 0) {
if (s1[columnIndex - 1] === s2[rowIndex - 1]) { if (set1[columnIndex - 1] === set2[rowIndex - 1]) {
// Move by diagonal left-top. // Move by diagonal left-top.
lcs = s1[columnIndex - 1] + lcs; longestSequence.unshift(set1[columnIndex - 1]);
columnIndex -= 1; columnIndex -= 1;
rowIndex -= 1; rowIndex -= 1;
} else if (lcsMatrix[rowIndex][columnIndex] === lcsMatrix[rowIndex][columnIndex - 1]) { } else if (lcsMatrix[rowIndex][columnIndex] === lcsMatrix[rowIndex][columnIndex - 1]) {
@ -56,5 +56,5 @@ export default function longestCommonSubsequnce(s1, s2) {
} }
} }
return lcs; return longestSequence;
} }

View File

@ -1,13 +0,0 @@
import longestCommonSubsequnce from '../longestCommonSubsequnce';
describe('longestCommonSubsequnce', () => {
it('should find longest common subsequence for two strings', () => {
expect(longestCommonSubsequnce('', '')).toBe('');
expect(longestCommonSubsequnce('', 'ABC')).toBe('');
expect(longestCommonSubsequnce('ABC', '')).toBe('');
expect(longestCommonSubsequnce('ABC', 'DEFG')).toBe('');
expect(longestCommonSubsequnce('ABCDGH', 'AEDFHR')).toBe('ADH');
expect(longestCommonSubsequnce('AGGTAB', 'GXTXAYB')).toBe('GTAB');
expect(longestCommonSubsequnce('ABCDAF', 'ACBCF')).toBe('ABCF');
});
});