lcsFunctions = {
function longestCommonSubsequence(s1, s2) {
const m = s1.length;
const n = s2.length;
const C = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
if (s1[i - 1] === s2[j - 1]) {
C[i][j] = C[i - 1][j - 1] + 1;
}
else {
C[i][j] = Math.max(C[i][j - 1], C[i - 1][j]);
}
}
}
return C;
}
function backtrack(C, s1, s2, i, j) {
if (i === 0 || j === 0) {
return "";
}
else if (s1[i - 1] === s2[j - 1]) {
return backtrack(C, s1, s2, i - 1, j - 1) + s1[i - 1];
}
else {
return C[i][j - 1] > C[i - 1][j]
? backtrack(C, s1, s2, i, j - 1)
: backtrack(C, s1, s2, i - 1, j);
}
}
function generateOperations2(
text,
updateText
){
const m = text.length;
const n = updateText.length;
const C = longestCommonSubsequence(text, updateText);
const lcs = backtrack(C, text, updateText, m, n);
const ops= [];
const removeOps = [];
let i = 0,
j = 0;
for (const char of lcs) {
while (text[i] !== char) {
removeOps.push({
type: "remove_text",
offset: i,
text: text[i],
path: [],
});
i++;
}
while (updateText[j] !== char) {
ops.push({
type: "insert_text",
offset: i,
text: updateText[j],
path: [],
});
j++;
}
i++;
j++;
}
while (i < m) {
removeOps.push({ type: "remove_text", offset: i, text: text[i], path: [] });
i++;
}
while (j < n) {
ops.push({ type: "insert_text", offset: i, text: updateText[j], path: [] });
i++;
j++;
}
// Reverse the remove operations and merge with other ops.
return ops.concat(removeOps.reverse());
}
return { longestCommonSubsequence, backtrack, generateOperations2 };
}