UNPKG

@technobuddha/library

Version:
67 lines (58 loc) 2.11 kB
import create2DArray from '../create2DArray'; export type Options<T> = { /** * Function that acts as a custom comparator * for the array objects. Function should return true if objects are equal, otherwise false. * */ compare?: (a: T, b: T) => boolean; /** * Function used to decide what to return * as a result subsequence. It accepts 2 arguments: index of common element * in the first array and index in the second. The default function returns * element from the first array. */ collect?: (i1: number, i2: number) => T; }; /** * Implementation of Longest Common Subsequence problem. * http://en.wikipedia.org/wiki/Longest_common_subsequence * * Returns the longest possible array that is subarray of both of given arrays. * * @param array1 First array of objects. * @param array2 Second array of objects. * @param __namedParameters see {@link Options} * @default compare equality comparison * @default collect basic collector * @returns A list of objects that are common to both arrays * such that there is no common subsequence with size greater than the * length of the list. */ export function longestCommonSubsequence<T>(array1: ArrayLike<T>, array2: ArrayLike<T>, { compare = (a, b) => a === b, collect = (i1, _i2) => array1[i1] }: Options<T> = {}): T[] { const l1 = array1.length; const l2 = array2.length; const c = create2DArray(l1 + 1, l2 + 1, 0); let i: number; let j: number; for(i = 1; i <= l1; i++) { for(j = 1; j <= l2; j++) { if(compare(array1[i - 1], array2[j - 1])) c[i][j] = c[i - 1][j - 1] + 1; else c[i][j] = Math.max(c[i - 1][j], c[i][j - 1]); } } const result = [] as T[]; i = l1; j = l2; while(i > 0 && j > 0) { if(compare(array1[i - 1], array2[j - 1])) { result.unshift(collect(i - 1, j - 1)); i--; j--; } else if(c[i - 1][j] > c[i][j - 1]) { i--; } else { j--; } } return result; } export default longestCommonSubsequence;