forked from trekhleb/javascript-algorithms
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
132 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
src/algorithms/sets/shortest-common-supersequence/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Shortest Common Supersequence | ||
|
||
The shortest common supersequence (SCS) of two sequences `X` and `Y` | ||
is the shortest sequence which has `X` and `Y` as subsequences. | ||
|
||
In other words assume we're given two strings str1 and str2, find | ||
the shortest string that has both str1 and str2 as subsequences. | ||
|
||
This is a problem closely related to the longest common | ||
subsequence problem. | ||
|
||
## Example | ||
|
||
``` | ||
Input: str1 = "geek", str2 = "eke" | ||
Output: "geeke" | ||
Input: str1 = "AGGTAB", str2 = "GXTXAYB" | ||
Output: "AGXGTXAYB" | ||
``` | ||
|
||
## References | ||
|
||
- [GeeksForGeeks](https://www.geeksforgeeks.org/shortest-common-supersequence/) |
35 changes: 35 additions & 0 deletions
35
...lgorithms/sets/shortest-common-supersequence/__test__/shortestCommonSupersequence.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import shortestCommonSupersequence from '../shortestCommonSupersequence'; | ||
|
||
describe('shortestCommonSupersequence', () => { | ||
it('should find shortest common supersequence of two sequences', () => { | ||
// LCS (longest common subsequence) is empty | ||
expect(shortestCommonSupersequence( | ||
['A', 'B', 'C'], | ||
['D', 'E', 'F'], | ||
)).toEqual(['A', 'B', 'C', 'D', 'E', 'F']); | ||
|
||
// LCS (longest common subsequence) is "EE" | ||
expect(shortestCommonSupersequence( | ||
['G', 'E', 'E', 'K'], | ||
['E', 'K', 'E'], | ||
)).toEqual(['G', 'E', 'K', 'E', 'K']); | ||
|
||
// LCS (longest common subsequence) is "GTAB" | ||
expect(shortestCommonSupersequence( | ||
['A', 'G', 'G', 'T', 'A', 'B'], | ||
['G', 'X', 'T', 'X', 'A', 'Y', 'B'], | ||
)).toEqual(['A', 'G', 'G', 'X', 'T', 'X', 'A', 'Y', 'B']); | ||
|
||
// LCS (longest common subsequence) is "BCBA". | ||
expect(shortestCommonSupersequence( | ||
['A', 'B', 'C', 'B', 'D', 'A', 'B'], | ||
['B', 'D', 'C', 'A', 'B', 'A'], | ||
)).toEqual(['A', 'B', 'D', 'C', 'A', 'B', 'D', 'A', 'B']); | ||
|
||
// LCS (longest common subsequence) is "BDABA". | ||
expect(shortestCommonSupersequence( | ||
['B', 'D', 'C', 'A', 'B', 'A'], | ||
['A', 'B', 'C', 'B', 'D', 'A', 'B', 'A', 'C'], | ||
)).toEqual(['A', 'B', 'C', 'B', 'D', 'C', 'A', 'B', 'A', 'C']); | ||
}); | ||
}); |
71 changes: 71 additions & 0 deletions
71
src/algorithms/sets/shortest-common-supersequence/shortestCommonSupersequence.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import longestCommonSubsequnce from '../longest-common-subsequnce/longestCommonSubsequnce'; | ||
|
||
/** | ||
* @param {string[]} set1 | ||
* @param {string[]} set2 | ||
* @return {string[]} | ||
*/ | ||
|
||
export default function shortestCommonSupersequence(set1, set2) { | ||
// Let's first find the longest common subsequence of two sets. | ||
const lcs = longestCommonSubsequnce(set1, set2); | ||
|
||
// If LCS is empty then the shortest common supersequnce would be just | ||
// concatenation of two sequences. | ||
if (lcs.length === 1 && lcs[0] === '') { | ||
return set1.concat(set2); | ||
} | ||
|
||
// Now let's add elements of set1 and set2 in order before/inside/after the LCS. | ||
let supersequence = []; | ||
|
||
let setIndex1 = 0; | ||
let setIndex2 = 0; | ||
let lcsIndex = 0; | ||
let setOnHold1 = false; | ||
let setOnHold2 = false; | ||
|
||
while (lcsIndex < lcs.length) { | ||
// Add elements of the first set to supersequence in correct order. | ||
if (setIndex1 < set1.length) { | ||
if (!setOnHold1 && set1[setIndex1] !== lcs[lcsIndex]) { | ||
supersequence.push(set1[setIndex1]); | ||
setIndex1 += 1; | ||
} else { | ||
setOnHold1 = true; | ||
} | ||
} | ||
|
||
// Add elements of the second set to supersequence in correct order. | ||
if (setIndex2 < set2.length) { | ||
if (!setOnHold2 && set2[setIndex2] !== lcs[lcsIndex]) { | ||
supersequence.push(set2[setIndex2]); | ||
setIndex2 += 1; | ||
} else { | ||
setOnHold2 = true; | ||
} | ||
} | ||
|
||
// Add LCS element to the supersequence in correct order. | ||
if (setOnHold1 && setOnHold2) { | ||
supersequence.push(lcs[lcsIndex]); | ||
lcsIndex += 1; | ||
setIndex1 += 1; | ||
setIndex2 += 1; | ||
setOnHold1 = false; | ||
setOnHold2 = false; | ||
} | ||
} | ||
|
||
// Attach set1 leftovers. | ||
if (setIndex1 < set1.length) { | ||
supersequence = supersequence.concat(set1.slice(setIndex1)); | ||
} | ||
|
||
// Attach set2 leftovers. | ||
if (setIndex2 < set2.length) { | ||
supersequence = supersequence.concat(set2.slice(setIndex2)); | ||
} | ||
|
||
return supersequence; | ||
} |