From 57a5dcb2c7f55404ad31847dba461f57bd91c4c0 Mon Sep 17 00:00:00 2001 From: Sujay008 <45827775+sujaykaushik008@users.noreply.github.com> Date: Mon, 26 Oct 2020 00:51:24 +0530 Subject: [PATCH] feat: add palindrome partitioning algorithm (#1319) * feat: add palindrome partitioning algorithm * Update palindrome_partitioning.cpp * updating DIRECTORY.md * Update palindrome_partitioning.cpp Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + .../palindrome_partitioning.cpp | 123 ++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 dynamic_programming/palindrome_partitioning.cpp diff --git a/DIRECTORY.md b/DIRECTORY.md index c857306da..15283332c 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -67,6 +67,7 @@ * [Longest Increasing Subsequence](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/longest_increasing_subsequence.cpp) * [Longest Increasing Subsequence (Nlogn)](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/longest_increasing_subsequence_(nlogn).cpp) * [Matrix Chain Multiplication](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/matrix_chain_multiplication.cpp) + * [Palindrome Partitioning](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/palindrome_partitioning.cpp) * [Searching Of Element In Dynamic Array](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/searching_of_element_in_dynamic_array.cpp) * [Shortest Common Supersequence](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/shortest_common_supersequence.cpp) * [Tree Height](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/tree_height.cpp) diff --git a/dynamic_programming/palindrome_partitioning.cpp b/dynamic_programming/palindrome_partitioning.cpp new file mode 100644 index 000000000..b5ab4ed6c --- /dev/null +++ b/dynamic_programming/palindrome_partitioning.cpp @@ -0,0 +1,123 @@ +/** + * @file + * @brief Implements [Palindrome Partitioning](https://leetcode.com/problems/palindrome-partitioning-ii/) algorithm, giving you the minimum number of partitions you need to make + * + * @details + * palindrome partitioning uses dynamic programming and goes to all the possible partitions to find the minimum + * you are given a string and you need to give minimum number of partitions needed to divide it into a number of palindromes + * [Palindrome Partitioning] (https://www.geeksforgeeks.org/palindrome-partitioning-dp-17/) + * overall time complexity O(n^2) + * For example: example 1:- + * String : "nitik" + * Output : 2 => "n | iti | k" + * For example: example 2:- + * String : "ababbbabbababa" + * Output : 3 => "aba | b | bbabb | ababa" + * @author [Sujay Kaushik] (https://github.com/sujaykaushik008) + */ + +#include // for io operations +#include // for std::vector +#include // for std::min +#include // for std::assert +#include // for INT_MAX + +/** + * @namespace dynamic_programming + * @brief Dynamic Programming algorithms + */ +namespace dynamic_programming { + + /** + * @namespace palindrome_partitioning + * @brief Functions for [Palindrome Partitioning](https://leetcode.com/problems/palindrome-partitioning-ii/) algorithm + */ + namespace palindrome_partitioning { + + /** + * Function implementing palindrome partitioning algorithm using lookup table method. + * @param str input string + * @returns minimum number of partitions + */ + int pal_part(const std::string &str) { + + int n = str.size(); + + // creating lookup table for minimum number of cuts + std::vector > cuts(n, std::vector(n, 0)); + + // creating lookup table for palindrome checking + std::vector > is_palindrome(n, std::vector(n, false)); + + // initialization + for (int i = 0; i < n; i++) { + is_palindrome[i][i] = true; + cuts[i][i] = 0; + } + + for (int len = 2; len <= n; len++) { + for (int start_index = 0; start_index < n - len + 1; start_index++) { + + int end_index = start_index + len - 1; + + if (len == 2) { + is_palindrome[start_index][end_index] = (str[start_index] == str[end_index]); + } else { + is_palindrome[start_index][end_index] = + (str[start_index] == str[end_index]) && is_palindrome[start_index + 1][end_index - 1]; + } + + if (is_palindrome[start_index][end_index]) { + cuts[start_index][end_index] = 0; + } else { + cuts[start_index][end_index] = INT_MAX; + for (int partition = start_index; partition <= end_index - 1; partition++) { + cuts[start_index][end_index] = std::min(cuts[start_index][end_index], + cuts[start_index][partition] + + cuts[partition + 1][end_index] + 1); + } + } + } + } + + return cuts[0][n - 1]; + } + } // namespace palindrome_partitioning +} // namespace dynamic_programming + +/** + * @brief Test Function + * @return void +*/ +static void test() { + // custom input vector + std::vector custom_input{"nitik", "ababbbabbababa", "abdc"}; + + // calculated output vector by pal_part Function + std::vector calculated_output(3); + + for (int i = 0; i < 3; i++) { + calculated_output[i] = dynamic_programming::palindrome_partitioning::pal_part(custom_input[i]); + } + + // expected output vector + std::vector expected_output{2, 3, 3}; + + // Testing implementation via assert function + // It will throw error if any of the expected test fails + // Else it will give nothing + for (int i = 0; i < 3; i++) { + assert(expected_output[i] == calculated_output[i]); + } + + std::cout << "All tests passed successfully!\n"; +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // execute the test + return 0; +}