1- // Longest common substring via Dynamic Programming
2- // longest_common_substring(a, b) returns the length of longest common substring between the strings a and b.
3- pub fn longest_common_substring ( text1 : & str , text2 : & str ) -> i32 {
4- let m = text1. len ( ) ;
5- let n = text2. len ( ) ;
1+ //! This module provides a function to find the length of the longest common substring
2+ //! between two strings using dynamic programming.
63
7- let t1 = text1. as_bytes ( ) ;
8- let t2 = text2. as_bytes ( ) ;
4+ /// Finds the length of the longest common substring between two strings using dynamic programming.
5+ ///
6+ /// The algorithm uses a 2D dynamic programming table where each cell represents
7+ /// the length of the longest common substring ending at the corresponding indices in
8+ /// the two input strings. The maximum value in the DP table is the result, i.e., the
9+ /// length of the longest common substring.
10+ ///
11+ /// The time complexity is `O(n * m)`, where `n` and `m` are the lengths of the two strings.
12+ /// # Arguments
13+ ///
14+ /// * `s1` - The first input string.
15+ /// * `s2` - The second input string.
16+ ///
17+ /// # Returns
18+ ///
19+ /// Returns the length of the longest common substring between `s1` and `s2`.
20+ pub fn longest_common_substring ( s1 : & str , s2 : & str ) -> usize {
21+ let mut substr_len = vec ! [ vec![ 0 ; s2. len( ) + 1 ] ; s1. len( ) + 1 ] ;
22+ let mut max_len = 0 ;
923
10- // BottomUp Tabulation
11- let mut dp = vec ! [ vec![ 0 ; n + 1 ] ; m + 1 ] ;
12- let mut ans = 0 ;
13- for i in 1 ..=m {
14- for j in 1 ..=n {
15- if t1[ i - 1 ] == t2[ j - 1 ] {
16- dp[ i] [ j] = 1 + dp[ i - 1 ] [ j - 1 ] ;
17- ans = std:: cmp:: max ( ans, dp[ i] [ j] ) ;
24+ s1. as_bytes ( ) . iter ( ) . enumerate ( ) . for_each ( |( i, & c1) | {
25+ s2. as_bytes ( ) . iter ( ) . enumerate ( ) . for_each ( |( j, & c2) | {
26+ if c1 == c2 {
27+ substr_len[ i + 1 ] [ j + 1 ] = substr_len[ i] [ j] + 1 ;
28+ max_len = max_len. max ( substr_len[ i + 1 ] [ j + 1 ] ) ;
1829 }
19- }
20- }
30+ } ) ;
31+ } ) ;
2132
22- ans
33+ max_len
2334}
2435
2536#[ cfg( test) ]
@@ -28,28 +39,32 @@ mod tests {
2839
2940 macro_rules! test_longest_common_substring {
3041 ( $( $name: ident: $inputs: expr, ) * ) => {
31- $(
32- #[ test]
33- fn $name( ) {
34- let ( text1 , text2 , expected) = $inputs;
35- assert_eq!( longest_common_substring( text1 , text2 ) , expected) ;
36- assert_eq!( longest_common_substring( text2 , text1 ) , expected) ;
37- }
38- ) *
42+ $(
43+ #[ test]
44+ fn $name( ) {
45+ let ( s1 , s2 , expected) = $inputs;
46+ assert_eq!( longest_common_substring( s1 , s2 ) , expected) ;
47+ assert_eq!( longest_common_substring( s2 , s1 ) , expected) ;
48+ }
49+ ) *
3950 }
4051 }
4152
4253 test_longest_common_substring ! {
43- empty_inputs: ( "" , "" , 0 ) ,
44- one_empty_input: ( "" , "a" , 0 ) ,
45- single_same_char_input: ( "a" , "a" , 1 ) ,
46- single_different_char_input: ( "a" , "b" , 0 ) ,
47- regular_input_0: ( "abcdef" , "bcd" , 3 ) ,
48- regular_input_1: ( "abcdef" , "xabded" , 2 ) ,
49- regular_input_2: ( "GeeksforGeeks" , "GeeksQuiz" , 5 ) ,
50- regular_input_3: ( "abcdxyz" , "xyzabcd" , 4 ) ,
51- regular_input_4: ( "zxabcdezy" , "yzabcdezx" , 6 ) ,
52- regular_input_5: ( "OldSite:GeeksforGeeks.org" , "NewSite:GeeksQuiz.com" , 10 ) ,
53- regular_input_6: ( "aaaaaaaaaaaaa" , "bbb" , 0 ) ,
54+ test_empty_strings: ( "" , "" , 0 ) ,
55+ test_one_empty_string: ( "" , "a" , 0 ) ,
56+ test_identical_single_char: ( "a" , "a" , 1 ) ,
57+ test_different_single_char: ( "a" , "b" , 0 ) ,
58+ test_common_substring_at_start: ( "abcdef" , "abc" , 3 ) ,
59+ test_common_substring_at_middle: ( "abcdef" , "bcd" , 3 ) ,
60+ test_common_substring_at_end: ( "abcdef" , "def" , 3 ) ,
61+ test_no_common_substring: ( "abc" , "xyz" , 0 ) ,
62+ test_overlapping_substrings: ( "abcdxyz" , "xyzabcd" , 4 ) ,
63+ test_special_characters: ( "@abc#def$" , "#def@" , 4 ) ,
64+ test_case_sensitive: ( "abcDEF" , "ABCdef" , 0 ) ,
65+ test_full_string_match: ( "GeeksforGeeks" , "GeeksforGeeks" , 13 ) ,
66+ test_substring_with_repeated_chars: ( "aaaaaaaaaaaaa" , "aaa" , 3 ) ,
67+ test_longer_strings_with_common_substring: ( "OldSite:GeeksforGeeks.org" , "NewSite:GeeksQuiz.com" , 10 ) ,
68+ test_no_common_substring_with_special_chars: ( "!!!" , "???" , 0 ) ,
5469 }
5570}
0 commit comments