mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-26 07:01:18 +08:00
Add SCS.
This commit is contained in:
parent
3a984b6d4e
commit
c9089bb5f3
@ -39,6 +39,7 @@
|
|||||||
* [Fisher–Yates Shuffle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/fisher-yates) - random permutation of a finite sequence
|
* [Fisher–Yates 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)
|
* [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequnce) (LCS)
|
||||||
* [Longest Increasing subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence)
|
* [Longest Increasing subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence)
|
||||||
|
* [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence) (SCS)
|
||||||
* **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
|
||||||
@ -92,7 +93,7 @@
|
|||||||
* [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/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)
|
||||||
* [Longest Increasing subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence)
|
* [Longest Increasing subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence)
|
||||||
* Shortest common supersequence
|
* [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence)
|
||||||
* Knapsack problem
|
* Knapsack problem
|
||||||
* Maximum subarray
|
* Maximum subarray
|
||||||
* Maximum sum path
|
* Maximum sum path
|
||||||
|
24
src/algorithms/sets/shortest-common-supersequence/README.md
Normal file
24
src/algorithms/sets/shortest-common-supersequence/README.md
Normal file
@ -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/)
|
@ -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']);
|
||||||
|
});
|
||||||
|
});
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user