You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
2.6 KiB
JavaScript

(function (exports) {
'use strict';
exports.longestCommonSubsequence = (function () {
/**
* Find the lengths of longest common sub-sequences
* of two strings and their substrings.
*
* Complexity: O(MN).
*
* @private
* @param {String} first string
* @param {String} second string
* @return {Array} two dimensional array with LCS
* lengths of input strings and their substrings.
*
*/
function getLcsLengths(str1, str2) {
var result = [];
for (var i = -1; i < str1.length; i = i + 1) {
result[i] = [];
for (var j = -1; j < str2.length; j = j + 1) {
if (i === -1 || j === -1) {
result[i][j] = 0;
} else if (str1[i] === str2[j]) {
result[i][j] = result[i - 1][j - 1] + 1;
} else {
result[i][j] = Math.max(result[i - 1][j], result[i][j - 1]);
}
}
}
return result;
}
/**
* Find longest common sub-sequences of two strings.
*
* Complexity: O(M + N).
*
* @private
* @param {String} first string
* @param {String} second string
* @return {Array} two dimensional array with LCS
* lengths of input strings and their substrings
* returned from 'getLcsLengths' function.
*
*/
function getLcs(str1, str2, lcsLengthsMatrix) {
var execute = function (i, j) {
if (!lcsLengthsMatrix[i][j]) {
return '';
} else if (str1[i] === str2[j]) {
return execute(i - 1, j - 1) + str1[i];
} else if (lcsLengthsMatrix[i][j - 1] > lcsLengthsMatrix[i - 1][j]) {
return execute(i, j - 1);
} else {
return execute(i - 1, j);
}
};
return execute(str1.length - 1, str2.length - 1);
}
/**
* Algorithm from dynamic programming. It finds the longest
* common sub-sequence of two strings. For example for strings 'abcd'
* and 'axxcda' the longest common sub-sequence is 'acd'.
*
* @example
* var subsequence = require('path-to-algorithms/src/searching/'+
* 'longest-common-subsequence').longestCommonSubsequence;
* console.log(subsequence('abcd', 'axxcda'); // 'acd'
*
* @public
* @module searching/longest-common-subsequence
* @param {String} first input string.
* @param {String} second input string.
* @return {Array} Longest common subsequence.
*/
return function (str1, str2) {
var lcsLengthsMatrix = getLcsLengths(str1, str2);
return getLcs(str1, str2, lcsLengthsMatrix);
};
})();
})(typeof window === 'undefined' ? module.exports : window);