51bac1f1dc60d1db89af8df9a599709c53d69d88
[GitHub/WoltLab/WCF.git] /
1 <?php declare(strict_types=1);
2 /*
3 * This file is part of sebastian/diff.
4 *
5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10 namespace SebastianBergmann\Diff;
11
12 use function array_reverse;
13 use function count;
14 use function max;
15 use SplFixedArray;
16
17 final class TimeEfficientLongestCommonSubsequenceCalculator implements LongestCommonSubsequenceCalculator
18 {
19 /**
20 * @inheritDoc
21 */
22 public function calculate(array $from, array $to): array
23 {
24 $common = [];
25 $fromLength = count($from);
26 $toLength = count($to);
27 $width = $fromLength + 1;
28 $matrix = new SplFixedArray($width * ($toLength + 1));
29
30 for ($i = 0; $i <= $fromLength; $i++) {
31 $matrix[$i] = 0;
32 }
33
34 for ($j = 0; $j <= $toLength; $j++) {
35 $matrix[$j * $width] = 0;
36 }
37
38 for ($i = 1; $i <= $fromLength; $i++) {
39 for ($j = 1; $j <= $toLength; $j++) {
40 $o = ($j * $width) + $i;
41 $matrix[$o] = max(
42 $matrix[$o - 1],
43 $matrix[$o - $width],
44 $from[$i - 1] === $to[$j - 1] ? $matrix[$o - $width - 1] + 1 : 0
45 );
46 }
47 }
48
49 $i = $fromLength;
50 $j = $toLength;
51
52 while ($i > 0 && $j > 0) {
53 if ($from[$i - 1] === $to[$j - 1]) {
54 $common[] = $from[$i - 1];
55 $i--;
56 $j--;
57 } else {
58 $o = ($j * $width) + $i;
59
60 if ($matrix[$o - $width] > $matrix[$o - 1]) {
61 $j--;
62 } else {
63 $i--;
64 }
65 }
66 }
67
68 return array_reverse($common);
69 }
70 }