Đây là một hàm ngắn bạn có thể sử dụng để tìm hai mảng. Nó thực hiện thuật toán LCS :
function computeDiff($from, $to)
{
$diffValues = array();
$diffMask = array();
$dm = array();
$n1 = count($from);
$n2 = count($to);
for ($j = -1; $j < $n2; $j++) $dm[-1][$j] = 0;
for ($i = -1; $i < $n1; $i++) $dm[$i][-1] = 0;
for ($i = 0; $i < $n1; $i++)
{
for ($j = 0; $j < $n2; $j++)
{
if ($from[$i] == $to[$j])
{
$ad = $dm[$i - 1][$j - 1];
$dm[$i][$j] = $ad + 1;
}
else
{
$a1 = $dm[$i - 1][$j];
$a2 = $dm[$i][$j - 1];
$dm[$i][$j] = max($a1, $a2);
}
}
}
$i = $n1 - 1;
$j = $n2 - 1;
while (($i > -1) || ($j > -1))
{
if ($j > -1)
{
if ($dm[$i][$j - 1] == $dm[$i][$j])
{
$diffValues[] = $to[$j];
$diffMask[] = 1;
$j--;
continue;
}
}
if ($i > -1)
{
if ($dm[$i - 1][$j] == $dm[$i][$j])
{
$diffValues[] = $from[$i];
$diffMask[] = -1;
$i--;
continue;
}
}
{
$diffValues[] = $from[$i];
$diffMask[] = 0;
$i--;
$j--;
}
}
$diffValues = array_reverse($diffValues);
$diffMask = array_reverse($diffMask);
return array('values' => $diffValues, 'mask' => $diffMask);
}
Nó tạo ra hai mảng:
- mảng giá trị: một danh sách các phần tử khi chúng xuất hiện trong diff.
- mảng mặt nạ: chứa số. 0: không thay đổi, -1: đã xóa, 1: đã thêm.
Nếu bạn điền vào một mảng với các ký tự, nó có thể được sử dụng để tính toán sự khác biệt nội tuyến. Bây giờ chỉ là một bước duy nhất để làm nổi bật sự khác biệt:
function diffline($line1, $line2)
{
$diff = computeDiff(str_split($line1), str_split($line2));
$diffval = $diff['values'];
$diffmask = $diff['mask'];
$n = count($diffval);
$pmc = 0;
$result = '';
for ($i = 0; $i < $n; $i++)
{
$mc = $diffmask[$i];
if ($mc != $pmc)
{
switch ($pmc)
{
case -1: $result .= '</del>'; break;
case 1: $result .= '</ins>'; break;
}
switch ($mc)
{
case -1: $result .= '<del>'; break;
case 1: $result .= '<ins>'; break;
}
}
$result .= $diffval[$i];
$pmc = $mc;
}
switch ($pmc)
{
case -1: $result .= '</del>'; break;
case 1: $result .= '</ins>'; break;
}
return $result;
}
Ví dụ.:
echo diffline('StackOverflow', 'ServerFault')
Sẽ xuất:
S<del>tackO</del><ins>er</ins>ver<del>f</del><ins>Fau</ins>l<del>ow</del><ins>t</ins>
StackOngười tẩyfFaulcon nợt
Ghi chú bổ sung:
- Ma trận diff yêu cầu các phần tử (m + 1) * (n + 1). Vì vậy, bạn có thể gặp phải lỗi bộ nhớ nếu bạn cố gắng để các chuỗi dài khác nhau. Trong trường hợp này, các phần khác nhau lớn hơn (ví dụ: dòng) trước, sau đó tìm nội dung của chúng trong một lượt thứ hai.
- Thuật toán có thể được cải thiện nếu bạn cắt các phần tử phù hợp từ đầu và cuối, sau đó chỉ chạy thuật toán ở giữa khác nhau. Một phiên bản sau (cồng kềnh hơn) cũng chứa những sửa đổi này.