@@ -2,8 +2,6 @@ use std::cmp::max;
22use std:: cmp:: Ordering ;
33use std:: collections:: HashMap ;
44
5- const IMPOSSIBLE_NB : usize = usize:: MAX ;
6-
75// alphabet : the common alphabet
86// chains : the strings among which the common subsequence is
97// d : the number of strings
@@ -16,11 +14,11 @@ struct Context {
1614 alphabet : Vec < char > ,
1715 chains : Vec < Vec < char > > ,
1816 d : usize ,
19- f : HashMap < Vec < usize > , u64 > ,
20- g : HashMap < Vec < usize > , u64 > ,
17+ f : HashMap < Vec < Option < usize > > , u64 > ,
18+ g : HashMap < Vec < Option < usize > > , u64 > ,
2119 ms : Vec < Vec < Vec < u64 > > > ,
22- mt : Vec < Vec < Vec < usize > > > ,
23- parents : HashMap < Vec < usize > , Option < Vec < usize > > > ,
20+ mt : Vec < Vec < Vec < Option < usize > > > > ,
21+ parents : HashMap < Vec < Option < usize > > , Option < Vec < Option < usize > > > > ,
2422}
2523
2624impl Context {
@@ -34,15 +32,15 @@ impl Context {
3432 let ms: Vec < Vec < Vec < u64 > > > = matrices_score ( & chains) ;
3533
3634 // an impossible to reach point, father of all points
37- let p0 = vec ! [ IMPOSSIBLE_NB ; d] ;
35+ let p0 = vec ! [ None ; d] ;
3836
39- let mut parents: HashMap < _ , Option < Vec < usize > > > = HashMap :: new ( ) ;
37+ let mut parents: HashMap < _ , Option < Vec < Option < usize > > > > = HashMap :: new ( ) ;
4038 parents. insert ( p0. clone ( ) , None ) ;
4139
4240 let mut g = HashMap :: new ( ) ;
4341 g. insert ( p0. clone ( ) , 0 ) ;
4442
45- let mut f: HashMap < Vec < usize > , u64 > = HashMap :: new ( ) ;
43+ let mut f: HashMap < Vec < Option < usize > > , u64 > = HashMap :: new ( ) ;
4644 f. insert ( p0, 0 ) ;
4745
4846 let mt = mt_table ( & chains, & mut alphabet) ;
@@ -61,7 +59,7 @@ impl Context {
6159
6260 // given a point p and his successor q, computes necessary informations
6361 // point p is marked PARENT of q
64- pub fn update_suc ( & mut self , p : Vec < usize > , q : Vec < usize > ) {
62+ pub fn update_suc ( & mut self , p : Vec < Option < usize > > , q : Vec < Option < usize > > ) {
6563 // g(q) = g(p) + 1
6664 let nb = & self . g [ & p] + 1 ;
6765 self . g . insert ( q. clone ( ) , nb) ;
@@ -82,17 +80,22 @@ impl Context {
8280 ///
8381 /// # Returns
8482 /// An array of the successors
85- pub fn get_successors ( & self , p : & [ usize ] ) -> Vec < Vec < usize > > {
86- let mut successors: Vec < Vec < usize > > = vec ! [ ] ;
83+ pub fn get_successors ( & self , p : & [ Option < usize > ] ) -> Vec < Vec < Option < usize > > > {
84+ let mut successors: Vec < Vec < Option < usize > > > = vec ! [ ] ;
8785
8886 // for all alphabet letters
8987 for ( ch_idx, _) in self . alphabet . iter ( ) . enumerate ( ) {
9088 // for each string, finds the next position of that letter
91- let mut succ: Vec < usize > = vec ! [ ] ;
89+ let mut succ: Vec < Option < usize > > = vec ! [ ] ;
9290 for ( i, p_ith_elt) in p. iter ( ) . enumerate ( ) . take ( self . chains . len ( ) ) {
93- let next_ch_idx = self . mt [ ch_idx] [ i] [ p_ith_elt + 1 ] ;
94- // in case the letter is not rechable in the string
95- if next_ch_idx == IMPOSSIBLE_NB {
91+
92+ let next_ch_idx = match p_ith_elt {
93+ Some ( idx) => self . mt [ ch_idx] [ i] [ idx + 1 ] ,
94+ None => continue , // Skip if current position is None
95+ } ;
96+
97+ // in case the letter is not reachable in the string
98+ if next_ch_idx. is_none ( ) {
9699 break ;
97100 }
98101
@@ -109,14 +112,17 @@ impl Context {
109112 }
110113
111114 // ascend back up the parent tree to form the common subsequence
112- fn common_seq ( & self , p : & Vec < usize > ) -> String {
115+ fn common_seq ( & self , p : & Vec < Option < usize > > ) -> String {
113116 let ref_str: & Vec < char > = & self . chains [ 0 ] ;
114117 let mut common_subsequence: Vec < char > = vec ! [ ] ;
115118 // Gaining mutability
116119 let mut p = p;
117120
118121 while self . parents [ p] . is_some ( ) {
119- common_subsequence. push ( ref_str[ p[ 0 ] ] ) ;
122+ // Get the first element of p, which is the position in the first string
123+ if let Some ( idx) = p[ 0 ] {
124+ common_subsequence. push ( ref_str[ idx] ) ;
125+ }
120126
121127 // getting the parent of current point
122128 p = self . parents [ p] . as_ref ( ) . unwrap ( ) ;
@@ -126,16 +132,16 @@ impl Context {
126132 }
127133
128134 /// CF Initqueue
129- fn get_starting_p ( & self ) -> Vec < Vec < usize > > {
130- let mut successors: Vec < Vec < usize > > = vec ! [ ] ;
135+ fn get_starting_p ( & self ) -> Vec < Vec < Option < usize > > > {
136+ let mut successors: Vec < Vec < Option < usize > > > = vec ! [ ] ;
131137
132138 // for each alphabet letter, finds the next match
133139 // meaning the a point where all strings share a character
134140 // example: In ["AB", "BC", "CB", "BF"],
135141 // A match for the letter B would be p = (1, 0, 1, 0)
136142 for ( ch_idx, _) in self . alphabet . iter ( ) . enumerate ( ) {
137143 // for each string, finds the next position of that letter
138- let mut succ: Vec < usize > = vec ! [ ] ;
144+ let mut succ: Vec < Option < usize > > = vec ! [ ] ;
139145 for i in 0 ..( self . chains . len ( ) ) {
140146 // gets the next position of the current letter
141147 let next_ch_idx = self . mt [ ch_idx] [ i] [ 0 ] ;
@@ -152,17 +158,20 @@ impl Context {
152158 /// Computes the heuristic function given a point
153159 /// min ( { M_ij[ p[i] ][ p[j] ] | (i,j) in [0 ; d] } )
154160 /// [Documentation](https://github.com/epita-rs/MLCS/blob/main/doc/paper.pdf)
155- fn heuristic ( & self , p : & [ usize ] ) -> u64 {
161+ fn heuristic ( & self , p : & [ Option < usize > ] ) -> u64 {
156162 let mut similarity: Vec < u64 > = vec ! [ ] ;
157163 for i in 0 ..self . d {
158164 for j in 0 ..self . d {
159165 if i != j {
160- similarity. push ( self . ms [ to_linear_index ( i, j, self . d ) ] [ p[ i] ] [ p[ j] ] ) ;
166+ // Skip if either point is None
167+ if let ( Some ( pi) , Some ( pj) ) = ( p[ i] , p[ j] ) {
168+ similarity. push ( self . ms [ to_linear_index ( i, j, self . d ) ] [ pi] [ pj] ) ;
169+ }
161170 }
162171 }
163172 }
164173
165- * similarity. iter ( ) . min ( ) . unwrap ( )
174+ similarity. iter ( ) . min ( ) . copied ( ) . unwrap_or ( 0 )
166175 }
167176
168177 /// Add the first matches to the queue
@@ -173,11 +182,11 @@ impl Context {
173182 ///
174183 /// * `self' - A structure containing informations
175184 /// * 'queue' - The priority queue of points
176- fn init_queue ( & mut self ) -> Vec < Vec < usize > > {
185+ fn init_queue ( & mut self ) -> Vec < Vec < Option < usize > > > {
177186 let mut queue = self . get_starting_p ( ) ;
178187
179188 for q in queue. clone ( ) {
180- self . update_suc ( vec ! [ IMPOSSIBLE_NB ; self . d] , q. clone ( ) ) ;
189+ self . update_suc ( vec ! [ None ; self . d] , q. clone ( ) ) ;
181190 }
182191
183192 self . reorder_queue ( & mut queue) ;
@@ -186,7 +195,7 @@ impl Context {
186195 }
187196
188197 // sorts the queue
189- fn reorder_queue ( & self , queue : & mut [ Vec < usize > ] ) {
198+ fn reorder_queue ( & self , queue : & mut [ Vec < Option < usize > > ] ) {
190199 queue. sort_unstable_by ( |p, q| {
191200 if ( self . f . get ( p) > self . f . get ( q) )
192201 || ( self . f . get ( p) == self . f . get ( q) && self . heuristic ( p) > self . heuristic ( q) )
@@ -249,20 +258,20 @@ fn matrices_score(chains: &[Vec<char>]) -> Vec<Vec<Vec<u64>>> {
249258/// An array of matrices.
250259/// Each matrix is tied to a string and can indicate, given a letter,
251260/// the next position of that letter in the string.
252- fn mt_table ( chains : & Vec < Vec < char > > , alphabet : & mut Vec < char > ) -> Vec < Vec < Vec < usize > > > {
253- let mut mt: Vec < Vec < Vec < usize > > > = vec ! [ ] ;
261+ fn mt_table ( chains : & Vec < Vec < char > > , alphabet : & mut Vec < char > ) -> Vec < Vec < Vec < Option < usize > > > > {
262+ let mut mt: Vec < Vec < Vec < Option < usize > > > > = vec ! [ ] ;
254263
255264 for ch in alphabet. clone ( ) {
256- let mut chain: Vec < Vec < usize > > = vec ! [ ] ;
265+ let mut chain: Vec < Vec < Option < usize > > > = vec ! [ ] ;
257266
258267 for s in chains {
259- let mut v: Vec < usize > = vec ! [ IMPOSSIBLE_NB ; s. len( ) ] ;
260- let mut lpos = IMPOSSIBLE_NB ;
268+ let mut v: Vec < Option < usize > > = vec ! [ None ; s. len( ) ] ;
269+ let mut lpos = None ;
261270
262271 // iterating backwards on the string
263272 for i in ( 0 ..( s. len ( ) ) ) . rev ( ) {
264273 if s[ i] == ch {
265- lpos = i ;
274+ lpos = Some ( i ) ;
266275 }
267276 // pushing the index of the last encounter with the current letter
268277 v[ i] = lpos;
@@ -272,7 +281,7 @@ fn mt_table(chains: &Vec<Vec<char>>, alphabet: &mut Vec<char>) -> Vec<Vec<Vec<us
272281
273282 // if the letter was never seen in the current string
274283 // then it can't part of the common alphabet
275- if lpos == IMPOSSIBLE_NB {
284+ if lpos. is_none ( ) {
276285 // removing that letter
277286 alphabet. retain ( |& x| x != ch) ;
278287 chain = vec ! [ ] ;
@@ -282,16 +291,6 @@ fn mt_table(chains: &Vec<Vec<char>>, alphabet: &mut Vec<char>) -> Vec<Vec<Vec<us
282291
283292 // the letter was seen at leat once
284293 if !chain. is_empty ( ) {
285- // pushing an array or array
286- // example on ["AB", "ABAA"]
287- // string1 => {
288- // 'A' => {0, IMPOSSIBLE_NB}
289- // 'B' => {1, 1}
290- // }
291- // string2 => {
292- // 'A' => {0, 2, 2, 3}
293- // 'B' => {1, 1, IMPOSSIBLE_NB, IMPOSSIBLE_NB}
294- // }
295294 mt. push ( chain) ;
296295 }
297296 }
@@ -317,7 +316,7 @@ pub fn multiple_longest_common_subsequence(chains: &Vec<&str>) -> String {
317316 let mut ctx = Context :: new ( chains) ;
318317
319318 // queue
320- let mut queue: Vec < Vec < usize > > = ctx. init_queue ( ) ;
319+ let mut queue: Vec < Vec < Option < usize > > > = ctx. init_queue ( ) ;
321320
322321 while !queue. is_empty ( ) {
323322 // y = max( {f(p) | p in queue} )
@@ -333,7 +332,7 @@ pub fn multiple_longest_common_subsequence(chains: &Vec<&str>) -> String {
333332 . clone ( )
334333 . into_iter ( )
335334 . filter ( |p| y <= ctx. f [ p] )
336- . collect :: < Vec < Vec < usize > > > ( ) ;
335+ . collect :: < Vec < Vec < Option < usize > > > > ( ) ;
337336 queue. clear ( ) ;
338337
339338 for p in second_queue {
@@ -432,7 +431,7 @@ mod tests {
432431 "=串-用2于测试2展67中中0xs中中中kkljhkkh示中测🚀测|测文|" ,
433432 "=串-|用2于ss串试056u展xx🚀示中lj测ggk测|ss文|" ,
434433 "=串-用2于-测22中中中uyty试串lj展gkks中示🚀测测s|测中文|b" ,
435- "=串用2于测s -试2中中0中hgtihlkk展串🚀中示s中|文|" ,
434+ "=串-用2于测s -试2中中0中hgtihlkk展串🚀中示s中|文|" ,
436435 "=2串2中2中2中s用-于0t测🚀j试展示测s测hkkkg测中中串文|l" ,
437436 "=2串2中2中2中s用-于0测🚀试展示测s中k中l串文|" ,
438437 "=2串2中2中2中s用ur-于0测🚀试展示测jkjljkkllkskg中串文|;" ,
@@ -489,4 +488,4 @@ mod tests {
489488 ) ,
490489
491490 }
492- }
491+ }
0 commit comments