diff --git a/dynamic_programming/longest_common_string.cpp b/dynamic_programming/longest_common_string.cpp index 81fa8a002..47e423d92 100644 --- a/dynamic_programming/longest_common_string.cpp +++ b/dynamic_programming/longest_common_string.cpp @@ -1,53 +1,159 @@ -#include -using namespace std; +/** + * @file + * @brief contains the definition of the function ::longest_common_string_length + * @details + * the function ::longest_common_string_length computes the length + * of the longest common string which can be created of two input strings + * by removing characters from them + * + * @author [Nikhil Arora](https://github.com/nikhilarora068) + * @author [Piotr Idzik](https://github.com/vil02) + */ -int max(int a, int b) { return (a > b) ? a : b; } +#include /// for assert +#include /// for std::cout +#include /// for std::string +#include /// for std::move +#include /// for std::vector -int main() { - char str1[] = "DEFBCD"; - char str2[] = "ABDEFJ"; - int i, j, k; - int n = strlen(str1) + 1; - int m = strlen(str2) + 1; - // cout<> sub_sols( + size_a + 1, std::vector(size_b + 1, 0)); - for (i = 0; i < m; i++) { - for (j = 0; j < n; j++) { - if (i == 0 || j == 0) - a[i][j] = 0; - - else if (str1[i - 1] == str2[j - 1]) - a[i][j] = a[i - 1][j - 1] + 1; - - else - a[i][j] = 0; - } - } - - /*for(i=0;i ma) { - ma = a[i][j]; - indi = i; - indj = j; + const auto limit = static_cast(-1); + for (std::size_t pos_a = size_a - 1; pos_a != limit; --pos_a) { + for (std::size_t pos_b = size_b - 1; pos_b != limit; --pos_b) { + if (string_a[pos_a] == string_b[pos_b]) { + sub_sols[pos_a][pos_b] = 1 + sub_sols[pos_a + 1][pos_b + 1]; + } else { + sub_sols[pos_a][pos_b] = std::max(sub_sols[pos_a + 1][pos_b], + sub_sols[pos_a][pos_b + 1]); } } } - cout << str1 << "\n"; - cout << str2 << "\n"; - - cout << "longest string size = " << ma /*<<" "< get_test_cases() { + return {TestCase("", "", 0), + TestCase("ab", "ab", 2), + TestCase("ab", "ba", 1), + TestCase("", "xyz", 0), + TestCase("abcde", "ace", 3), + TestCase("BADANA", "ANADA", 3), + TestCase("BADANA", "CANADAS", 3), + TestCase("a1a234a5aaaa6", "A1AAAA234AAA56AAAAA", 6), + TestCase("123x", "123", 3), + TestCase("12x3x", "123", 3), + TestCase("1x2x3x", "123", 3), + TestCase("x1x2x3x", "123", 3), + TestCase("x12x3x", "123", 3)}; +} + +/** + * @brief checks the function ::longest_common_string_length agains example data + * @param test_cases list of test cases + * @tparam type representing a list of test cases + */ +template +static void test_longest_common_string_length(const TestCases& test_cases) { + for (const auto& cur_tc : test_cases) { + assert(longest_common_string_length(cur_tc.string_a, cur_tc.string_b) == + cur_tc.common_string_len); + } +} + +/** + * @brief checks if the function ::longest_common_string_length returns the same + * result when its argument are flipped + * @param test_cases list of test cases + * @tparam type representing a list of test cases + */ +template +static void test_longest_common_string_length_is_symmetric( + const TestCases& test_cases) { + for (const auto& cur_tc : test_cases) { + assert(longest_common_string_length(cur_tc.string_b, cur_tc.string_a) == + cur_tc.common_string_len); + } +} + +/** + * @brief reverses a given string + * @param in_str input string + * @return the string in which the characters appear in the reversed order as in + * in_str + */ +std::string reverse_str(const std::string& in_str) { + return {in_str.rbegin(), in_str.rend()}; +} + +/** + * @brief checks if the function ::longest_common_string_length returns the same + * result when its inputs are reversed + * @param test_cases list of test cases + * @tparam type representing a list of test cases + */ +template +static void test_longest_common_string_length_for_reversed_inputs( + const TestCases& test_cases) { + for (const auto& cur_tc : test_cases) { + assert(longest_common_string_length(reverse_str(cur_tc.string_a), + reverse_str(cur_tc.string_b)) == + cur_tc.common_string_len); + } +} + +/** + * @brief runs all tests for ::longest_common_string_length funcion + */ +static void tests() { + const auto test_cases = get_test_cases(); + assert(test_cases.size() > 0); + test_longest_common_string_length(test_cases); + test_longest_common_string_length_is_symmetric(test_cases); + test_longest_common_string_length_for_reversed_inputs(test_cases); + + std::cout << "All tests have successfully passed!\n"; +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + tests(); + return 0; }