csd/lcsre.rs
1/// Find the longest repeating non-overlapping substring in cstr
2///
3/// The `longest_repeated_substring` function takes a null-terminated string and its length as input and
4/// returns the longest repeated non-overlapping substring in the string.
5///
6/// Arguments:
7///
8/// * `sv`: A reference to a character array representing the input string. It is assumed that the
9/// string is null-terminated.
10///
11/// Returns:
12///
13/// The function `longest_repeated_substring` returns a string, which is the longest repeated substring
14/// in the given input string `cstr`.
15///
16/// # Examples
17///
18/// ```
19/// use csd::lcsre::longest_repeated_substring;
20///
21/// let cs = "+-00+-00+-00+-0";
22/// assert_eq!(longest_repeated_substring(&cs), "+-00+-0");
23/// let cs = "abcdefgh";
24/// assert_eq!(longest_repeated_substring(&cs), "");
25/// ```
26#[allow(dead_code)]
27pub fn longest_repeated_substring(sv: &str) -> String {
28 let ndim = sv.len() + 1; // Dimension for the DP table (n+1 x n+1)
29 let mut lcsre = vec![vec![0usize; ndim]; ndim]; // DP table initialized with zeros
30
31 let mut res_length = 0; // To store length of the longest found substring
32
33 // Building table in bottom-up manner
34 let mut index = 0; // To store the starting index of the result substring
35 for i in 1..ndim {
36 for j in i + 1..ndim {
37 // Check if characters match and the substring wouldn't overlap
38 // (j-i) > lcsre[i-1][j-1] ensures non-overlapping condition
39 if sv.chars().nth(i - 1) == sv.chars().nth(j - 1) && lcsre[i - 1][j - 1] < (j - i) {
40 lcsre[i][j] = lcsre[i - 1][j - 1] + 1; // Extend the length of the common substring
41
42 // Update maximum length and starting index if we found a longer substring
43 if lcsre[i][j] > res_length {
44 res_length = lcsre[i][j];
45 index = i; // Store the ending index of the substring
46 }
47 } else {
48 lcsre[i][j] = 0; // Reset length if characters don't match
49 }
50 }
51 }
52
53 // Constructing the result substring if there's a non-empty result
54 if res_length > 0 {
55 // Extract substring from (index - length) to index
56 sv[index - res_length..index].to_string()
57 } else {
58 "".to_string() // Return empty string if no repeated substring found
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn test_lcsre() {
68 let cstr = "+-00+-00+-00+-0";
69 let res = longest_repeated_substring(cstr);
70 assert_eq!(res, "+-00+-0");
71 let cstr = "abcdefgh";
72 let res = longest_repeated_substring(cstr);
73 assert_eq!(res, "");
74 let cstr = "banana";
75 let res = longest_repeated_substring(cstr);
76 assert_eq!(res, "an");
77 let cstr = "";
78 let res = longest_repeated_substring(cstr);
79 assert_eq!(res, "");
80 let cstr = "aaaaa";
81 let res = longest_repeated_substring(cstr);
82 assert_eq!(res, "aa");
83 let cstr = "ababa";
84 let res = longest_repeated_substring(cstr);
85 assert_eq!(res, "ab");
86 }
87}