@@ -9,72 +9,25 @@ local function diff_u(fn1,fn2)
99 local function eol ()if c == ' \r ' then local d = f :read (1 )if not d then return true end f :seek (" cur" ,- 1 )return d ~= ' \n ' end return c == ' \n ' end
1010 o = o + 1 table.insert (l ,c )if eol ()then break end end
1111 if # l == 0 then break end l = table.concat (l )local ln ,c =# l ,crc32 (l )p = p .. string.pack (PF ,ln ,c ,ls )end f :close ()return p end
12- local f1 ,f2 ,ps ,i ,j ,la ,fh ,h ,w ,m ,u = open (fn1 ),open (fn2 ),string.packsize (PF ),1 ,1
12+ local f1 ,f2 ,ps ,i ,j ,la ,fh ,h ,w ,m ,u , L = open (fn1 ),open (fn2 ),string.packsize (PF ),1 ,1
1313 local function cmp (x ,y )
1414 local l1 ,c1 ,o1 ,l2 ,c2 ,o2 ,b1 ,e ,b2 ,f = string.unpack (PF ,f1 ,(x - 1 )* ps + 1 )l2 ,c2 ,o2 = string.unpack (PF ,f2 ,(y - 1 )* ps + 1 )if l1 ~= l2 or c1 ~= c2 then return false end
1515 local function li (fn ,o ,l )f ,e = io.open (fn ," rb" )if not f then return nil ,e end f :seek (S ,o )local g = f :read (l )f :close ()return g end
1616 b1 ,e ,b2 = li (fn1 ,o1 ,l1 )if not b1 then error (e )end b2 ,e = li (fn2 ,o2 ,l2 )if not b2 then error (e )end return b1 == b2 end
17- h ,w ,la ,m =# f1 // ps ,# f2 // ps ,1 ,{}
18- local function build (a1 ,a2 ,alo ,ahi ,blo ,bhi )
19- if alo > ahi or blo > bhi then return end
20- if alo == ahi then
21- for j = blo ,bhi do
22- if cmp (alo ,j ) then
23- m [# m + 1 ] = { x = alo , y = j , l = 1 }
24- break
25- end
26- end
27- return
28- end
29- local mid = (alo + ahi )// 2
30- -- forward DP from alo..mid
31- local F = {}
32- for j = blo , bhi do F [j ]= 0 end
33- for i = alo , mid do
34- local prev = 0
35- for j = blo , bhi do
36- local save = F [j ]
37- if cmp (i ,j ) then F [j ] = prev + 1
38- elseif F [j - 1 ] and F [j - 1 ] > F [j ] then F [j ] = F [j - 1 ] end
39- prev = save
40- end
41- end
42- -- backward DP from ahi..mid+1
43- local B = {}
44- for j = blo , bhi do B [j ]= 0 end
45- for i = ahi , mid + 1 , - 1 do
46- local prev = 0
47- for j = bhi , blo , - 1 do
48- local save = B [j ]
49- if cmp (i ,j ) then B [j ] = prev + 1
50- elseif B [j + 1 ] and B [j + 1 ] > B [j ] then B [j ] = B [j + 1 ] end
51- prev = save
52- end
53- end
54- -- find best split on the B-axis
55- local best ,jcut = - 1 ,blo
56- for j = blo ,bhi do
57- local s = (F [j ] or 0 ) + (B [j ] or 0 )
58- if s > best then best ,s ,jcut = s ,s ,j end
59- end
60- -- recurse on the two halves
61- build (a1 ,a2 ,alo , mid , blo , jcut )
62- build (a1 ,a2 ,mid + 1 ,ahi , jcut + 1 , bhi )
63- end
17+ h ,w ,la ,m ,L =# f1 // ps ,# f2 // ps ,1 ,{},{}
18+ -- full matrix LCS
19+ for x = 0 ,h do L [x ]= {}for y = 0 ,w do if x == 0 or y == 0 then L [x ][y ]= 0
20+ elseif cmp (x ,y )then L [x ][y ]= L [x - 1 ][y - 1 ]+ 1
21+ else L [x ][y ]= (L [x - 1 ][y ]> L [x ][y - 1 ])and L [x - 1 ][y ]or L [x ][y - 1 ]end end end
6422
65- build (fn1 ,fn2 , 1 , h , 1 , w )
23+ -- backtrack to extract the matching coordinates
24+ i ,j = h ,w while i > 0 and j > 0 do
25+ if cmp (i ,j )then table.insert (m ,1 ,{x = i ,y = j ,l = 1 })i ,j = i - 1 ,j - 1
26+ elseif L [i - 1 ][j ]>= L [i ][j - 1 ]then i = i - 1 else j = j - 1 end end
6627
67- local co = {}
68- for _ ,p in ipairs (m ) do
69- local t = co [# co ]
70- if t and t .x + t .l == p .x and t .y + t .l == p .y then
71- t .l = t .l + 1
72- else
73- co [# co + 1 ] = { x = p .x , y = p .y , l = 1 }
74- end
75- end
76- m = co
77- la = nil
28+ -- coalesce adjacent 1‐line runs into multi‐line matches
29+ local co = {}for _ ,p in ipairs (m )do local t = co [# co ] if t and t .x + t .l == p .x and t .y + t .l == p .y then t .l = t .l + 1 else co [# co + 1 ]= {x = p .x ,y = p .y ,l = p .l }end end
30+ m ,la ,i ,j = co ,nil ,1 ,1
7831
7932 local function get (fn ,p ,x )local l ,_ ,o ,f ,r = string.unpack (PF ,p ,(x - 1 )* ps + 1 )f = assert (io.open (fn ," rb" ))f :seek (S ,o )r = f :read (l )f :close ()return r end
8033 local function pfl (p ,s )return (p .. s :gsub (' \n $' ,' ' ):gsub (' \r $' ,' ' ))end
0 commit comments