// 文本比对算法 function textCompare(original, comparison) { // 将文本按字符分割为数组 const originalChars = [...original]; const comparisonChars = [...comparison]; // 计算最长公共子序列(LCS) const lcsMatrix = computeLCSMatrix(originalChars, comparisonChars); // 获取差异结果 const diffResult = getDiffResult(lcsMatrix, originalChars, comparisonChars); return diffResult; } // 计算LCS矩阵 function computeLCSMatrix(seq1, seq2) { const m = seq1.length; const n = seq2.length; const matrix = Array(m + 1).fill().map(() => Array(n + 1).fill(0)); for (let i = 1; i <= m; i++) { for (let j = 1; j <= n; j++) { if (seq1[i - 1] === seq2[j - 1]) { matrix[i][j] = matrix[i - 1][j - 1] + 1; } else { matrix[i][j] = Math.max(matrix[i - 1][j], matrix[i][j - 1]); } } } return matrix; } // 获取差异结果 function getDiffResult(matrix, seq1, seq2) { let i = seq1.length; let j = seq2.length; const result1 = []; // 原文结果 const result2 = []; // 对比文本结果 while (i > 0 || j > 0) { if (i > 0 && j > 0 && seq1[i - 1] === seq2[j - 1]) { // 字符相同 result1.unshift({ char: seq1[i - 1], type: 'same' }); result2.unshift({ char: seq2[j - 1], type: 'same' }); i--; j--; } else if (j > 0 && (i === 0 || matrix[i][j - 1] >= matrix[i - 1][j])) { // 对比文本有额外字符 result2.unshift({ char: seq2[j - 1], type: 'added' }); j--; } else if (i > 0 && (j === 0 || matrix[i][j - 1] < matrix[i - 1][j])) { // 原文有额外字符 result1.unshift({ char: seq1[i - 1], type: 'deleted' }); i--; } } return { original: result1, comparison: result2 }; } // 渲染比对结果 function renderComparison(result) { const originalResult = document.getElementById('originalResult'); const comparisonResult = document.getElementById('comparisonResult'); // 渲染原文 originalResult.innerHTML = ''; let currentSpan = null; result.original.forEach(item => { if (item.type === 'same') { if (currentSpan && currentSpan.className === 'highlight-red') { originalResult.appendChild(currentSpan); currentSpan = null; } if (!currentSpan || currentSpan.className !== 'same-text') { if (currentSpan) originalResult.appendChild(currentSpan); currentSpan = document.createElement('span'); currentSpan.className = 'same-text'; } currentSpan.textContent += item.char; } else { // deleted if (currentSpan && currentSpan.className === 'same-text') { originalResult.appendChild(currentSpan); currentSpan = null; } if (!currentSpan || currentSpan.className !== 'highlight-red') { if (currentSpan) originalResult.appendChild(currentSpan); currentSpan = document.createElement('span'); currentSpan.className = 'highlight-red'; } currentSpan.textContent += item.char; } }); if (currentSpan) originalResult.appendChild(currentSpan); // 渲染对比文本 currentSpan = null; comparisonResult.innerHTML = ''; result.comparison.forEach(item => { if (item.type === 'same') { if (currentSpan && currentSpan.className === 'highlight-green') { comparisonResult.appendChild(currentSpan); currentSpan = null; } if (!currentSpan || currentSpan.className !== 'same-text') { if (currentSpan) comparisonResult.appendChild(currentSpan); currentSpan = document.createElement('span'); currentSpan.className = 'same-text'; } currentSpan.textContent += item.char; } else { // added if (currentSpan && currentSpan.className === 'same-text') { comparisonResult.appendChild(currentSpan); currentSpan = null; } if (!currentSpan || currentSpan.className !== 'highlight-green') { if (currentSpan) comparisonResult.appendChild(currentSpan); currentSpan = document.createElement('span'); currentSpan.className = 'highlight-green'; } currentSpan.textContent += item.char; } }); if (currentSpan) comparisonResult.appendChild(currentSpan); } // 执行比对 function compareTexts() { const originalText = document.getElementById('originalText').value; const comparisonText = document.getElementById('comparisonText').value; const result = textCompare(originalText, comparisonText); renderComparison(result); } // 页面加载时执行一次比对 window.onload = compareTexts;