@wordpress/interactivity-router
Version:
Package that exposes state and actions from the `core/router` store, part of the Interactivity API.
62 lines (57 loc) • 1.93 kB
text/typescript
/**
* Calculates the Shortest Common Supersequence (SCS) of two sequences.
*
* A supersequence is a sequence that contains both input sequences as subsequences.
* The shortest common supersequence is the shortest possible such sequence.
*
* This implementation uses dynamic programming with a time complexity of O(mn)
* and space complexity of O(mn), where m and n are the lengths of sequences X and Y.
*
* @example
* ```ts
* const seq1 = [1, 3, 5];
* const seq2 = [2, 3, 4];
* const scs = shortestCommonSupersequence(seq1, seq2); // [1, 2, 3, 4, 5]
* ```
*
* @param X The first sequence.
* @param Y The second sequence.
* @param isEqual Optional equality function to compare elements.
* Defaults to strict equality (===).
* @return The shortest common supersequence of X and Y.
*/
export function shortestCommonSupersequence< E = unknown >(
X: E[],
Y: E[],
isEqual = ( a: E, b: E ) => a === b
) {
const m = X.length;
const n = Y.length;
// Create a 2D dp table where dp[i][j] is the SCS for X[0..i-1] and Y[0..j-1].
const dp: E[][][] = Array.from( { length: m + 1 }, () =>
Array( n + 1 ).fill( null )
);
// Base cases: one of the sequences is empty.
for ( let i = 0; i <= m; i++ ) {
dp[ i ][ 0 ] = X.slice( 0, i );
}
for ( let j = 0; j <= n; j++ ) {
dp[ 0 ][ j ] = Y.slice( 0, j );
}
// Fill in the dp table.
for ( let i = 1; i <= m; i++ ) {
for ( let j = 1; j <= n; j++ ) {
if ( isEqual( X[ i - 1 ], Y[ j - 1 ] ) ) {
// When X[i-1] equals Y[j-1], use the reference from X.
dp[ i ][ j ] = dp[ i - 1 ][ j - 1 ].concat( X[ i - 1 ] );
} else {
// Choose the shorter option between appending X[i-1] or Y[j-1].
const option1 = dp[ i - 1 ][ j ].concat( X[ i - 1 ] );
const option2 = dp[ i ][ j - 1 ].concat( Y[ j - 1 ] );
dp[ i ][ j ] =
option1.length <= option2.length ? option1 : option2;
}
}
}
return dp[ m ][ n ];
}