@@ -18,19 +18,30 @@ impl<T> Edit<T> {
18
18
}
19
19
}
20
20
21
- fn c_matrix < T : Same , I : Iterator < Item = T > , J : Iterator < Item = T > > (
21
+ fn c_matrix < T : Same , I , J > (
22
22
x : impl Fn ( ) -> I ,
23
23
y : impl Fn ( ) -> J ,
24
24
x_len : usize ,
25
25
y_len : usize ,
26
- ) -> crate :: twodvec:: TwoDVec < usize > {
27
- let width = x_len + 1 ;
28
- let height = y_len + 1 ;
26
+ ) -> ( usize , crate :: twodvec:: TwoDVec < usize > , usize )
27
+ where
28
+ I : DoubleEndedIterator < Item = T > ,
29
+ J : DoubleEndedIterator < Item = T > ,
30
+ {
31
+ let prefix_eq = x ( ) . zip ( y ( ) ) . take_while ( |( x, y) | x. same ( y) ) . count ( ) ;
32
+ let suffix_eq = x ( )
33
+ . rev ( )
34
+ . zip ( y ( ) . rev ( ) )
35
+ . take_while ( |( x, y) | x. same ( y) )
36
+ . count ( ) ;
37
+
38
+ let width = x_len. saturating_sub ( prefix_eq + suffix_eq) + 1 ;
39
+ let height = y_len. saturating_sub ( prefix_eq + suffix_eq) + 1 ;
29
40
30
41
let mut c = crate :: twodvec:: TwoDVec :: new ( 0 , width, height) ;
31
42
32
- for ( i, x) in x ( ) . enumerate ( ) {
33
- for ( j, y) in y ( ) . enumerate ( ) {
43
+ for ( i, x) in x ( ) . skip ( prefix_eq ) . take ( width - 1 ) . enumerate ( ) {
44
+ for ( j, y) in y ( ) . skip ( prefix_eq ) . take ( height - 1 ) . enumerate ( ) {
34
45
c[ j + 1 ] [ i + 1 ] = if x. same ( & y) {
35
46
c[ j] [ i] + 1
36
47
} else {
@@ -39,7 +50,7 @@ fn c_matrix<T: Same, I: Iterator<Item = T>, J: Iterator<Item = T>>(
39
50
}
40
51
}
41
52
42
- c
53
+ ( prefix_eq , c , suffix_eq )
43
54
}
44
55
45
56
fn lcs_base < T : Same > (
@@ -99,11 +110,29 @@ pub(crate) fn lcs<
99
110
x_len : usize ,
100
111
y_len : usize ,
101
112
) -> impl Iterator < Item = Edit < T > > {
102
- lcs_base (
103
- c_matrix ( || x ( ) , || y ( ) , x_len, y_len) ,
104
- itertools:: put_back ( x ( ) . rev ( ) ) ,
105
- itertools:: put_back ( y ( ) . rev ( ) ) ,
106
- )
113
+ let ( prefix_eq, c, suffix_eq) = c_matrix ( & x, & y, x_len, y_len) ;
114
+
115
+ x ( ) . zip ( y ( ) )
116
+ . take ( prefix_eq)
117
+ . map ( |( x, y) | Edit :: Same ( x, y) )
118
+ . chain ( lcs_base (
119
+ c,
120
+ itertools:: put_back (
121
+ x ( ) . rev ( )
122
+ . skip ( suffix_eq)
123
+ . take ( x_len. saturating_sub ( prefix_eq + suffix_eq) ) ,
124
+ ) ,
125
+ itertools:: put_back (
126
+ y ( ) . rev ( )
127
+ . skip ( suffix_eq)
128
+ . take ( y_len. saturating_sub ( prefix_eq + suffix_eq) ) ,
129
+ ) ,
130
+ ) )
131
+ . chain (
132
+ x ( ) . skip ( x_len - suffix_eq)
133
+ . zip ( y ( ) . skip ( y_len - suffix_eq) )
134
+ . map ( |( x, y) | Edit :: Same ( x, y) ) ,
135
+ )
107
136
}
108
137
109
138
// FIXME move out from lcs
0 commit comments