66 lines
2.0 KiB
JavaScript
66 lines
2.0 KiB
JavaScript
// @source https://github.com/trekhleb/javascript-algorithms/blob/master/src/algorithms/sets/longest-common-subsequence/longestCommonSubsequence.js
|
|
// @license MIT https://github.com/trekhleb/javascript-algorithms/blob/master/LICENSE
|
|
|
|
/**
|
|
* @param {string[]} set1
|
|
* @param {string[]} set2
|
|
* @return {string[]}
|
|
*/
|
|
export default function longestCommonSubsequence(set1, set2) {
|
|
// Init LCS matrix.
|
|
const lcsMatrix = Array(set2.length + 1)
|
|
.fill(null)
|
|
.map(() => Array(set1.length + 1).fill(null));
|
|
|
|
// Fill first row with zeros.
|
|
for (let columnIndex = 0; columnIndex <= set1.length; columnIndex += 1) {
|
|
lcsMatrix[0][columnIndex] = 0;
|
|
}
|
|
|
|
// Fill first column with zeros.
|
|
for (let rowIndex = 0; rowIndex <= set2.length; rowIndex += 1) {
|
|
lcsMatrix[rowIndex][0] = 0;
|
|
}
|
|
|
|
// Fill rest of the column that correspond to each of two strings.
|
|
for (let rowIndex = 1; rowIndex <= set2.length; rowIndex += 1) {
|
|
for (let columnIndex = 1; columnIndex <= set1.length; columnIndex += 1) {
|
|
if (set1[columnIndex - 1] === set2[rowIndex - 1]) {
|
|
lcsMatrix[rowIndex][columnIndex] = lcsMatrix[rowIndex - 1][columnIndex - 1] + 1;
|
|
} else {
|
|
lcsMatrix[rowIndex][columnIndex] = Math.max(
|
|
lcsMatrix[rowIndex - 1][columnIndex],
|
|
lcsMatrix[rowIndex][columnIndex - 1]
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Calculate LCS based on LCS matrix.
|
|
if (!lcsMatrix[set2.length][set1.length]) {
|
|
// If the length of largest common string is zero then return empty string.
|
|
return [""];
|
|
}
|
|
|
|
const longestSequence = [];
|
|
let columnIndex = set1.length;
|
|
let rowIndex = set2.length;
|
|
|
|
while (columnIndex > 0 || rowIndex > 0) {
|
|
if (set1[columnIndex - 1] === set2[rowIndex - 1]) {
|
|
// Move by diagonal left-top.
|
|
longestSequence.unshift(set1[columnIndex - 1]);
|
|
columnIndex -= 1;
|
|
rowIndex -= 1;
|
|
} else if (lcsMatrix[rowIndex][columnIndex] === lcsMatrix[rowIndex][columnIndex - 1]) {
|
|
// Move left.
|
|
columnIndex -= 1;
|
|
} else {
|
|
// Move up.
|
|
rowIndex -= 1;
|
|
}
|
|
}
|
|
|
|
return longestSequence;
|
|
}
|