var longestCommonSubsequence = (text1, text2, p1 = 0, p2 = 0, memo = initMemo(text1, text2)) => {
const isBaseCase = ((p1 === text1.length) || (p2 === text2.length));
if (isBaseCase) return 0;
const hasSeen = (memo[p1][p2] !== null);
if (hasSeen) return memo[p1][p2];
return dfs(text1, text2, p1, p2, memo);
}
var initMemo = (text1, text2) => new Array((text1.length + 1)).fill()
.map(() => new Array((text2.length + 1)).fill(null));
var dfs = (text1, text2, p1, p2, memo) => {
const left = longestCommonSubsequence(text1, text2, (p1 + 1), p2, memo);
const index = text2.indexOf(text1[p1], p2);
const isPrefix = (index !== -1);
const right = isPrefix
? (longestCommonSubsequence(text1, text2, (p1 + 1), (index + 1), memo) + 1)
: 0;
memo[p1][p2] = Math.max(left, right);
return memo[p1][p2];
}
var longestCommonSubsequence = (text1, text2, p1 = 0, p2 = 0, memo = initMemo(text1, text2)) => {
const isBaseCase = ((p1 === text1.length) || (p2 === text2.length));
if (isBaseCase) return 0;
const hasSeen = (memo[p1][p2] !== null);
if (hasSeen) return memo[p1][p2];
return dfs(text1, text2, p1, p2, memo);
}
var initMemo = (text1, text2) => new Array((text1.length + 1)).fill()
.map(() => new Array((text2.length + 1)).fill(null));
var dfs = (text1, text2, p1, p2, memo) => {
const left = (longestCommonSubsequence(text1, text2, (p1 + 1), (p2 + 1), memo) + 1);
const right =
Math.max(longestCommonSubsequence(text1, text2, p1, (p2 + 1), memo), longestCommonSubsequence(text1, text2, (p1 + 1), p2, memo));
const isEqual = (text1[p1] == text2[p2]);
const count = isEqual
? left
: right
memo[p1][p2] = count;
return memo[p1][p2];
}
var longestCommonSubsequence = (text1, text2) => {
const tabu = initTabu(text1, text2);
search(text1, text2, tabu);
return tabu[0][0];
};
var initTabu = (text1, text2) =>
new Array((text1.length + 1)).fill()
.map(() => new Array((text2.length + 1)).fill(0));
var search = (text1, text2, tabu) => {
const [ n, m ] = [ text1.length, text2.length ];
for (let x = (n - 1); (0 <= x); x--) {
for (let y = (m - 1); (0 <= y); y--) {
tabu[x][y] = (text1[x] === text2[y])
? (tabu[x + 1][y + 1] + 1)
: Math.max(tabu[x + 1][y], tabu[x][y + 1]);
}
}
}
var longestCommonSubsequence = (text1, text2) => {
const canSwap = (text2.length < text1.length);
if (canSwap) [ text1, text2 ] = [ text2, text1 ];
let tabu = initTabu(text1);
tabu = search(text1, text2, tabu);
return tabu[0];
};
var initTabu = (text1) => new Array((text1.length + 1)).fill(0)
var search = (text1, text2, tabu) => {
for (let col = (text2.length - 1); (0 <= col); col--) {
const temp = initTabu(text1);
for (let row = (text1.length - 1); (0 <= row); row--) {
const isEqual = (text1[row] == text2[col]);
temp[row] = isEqual
? (tabu[(row + 1)] + 1)
: Math.max(tabu[row], temp[(row + 1)]);
}
tabu = temp;
}
return tabu;
}