From 19330b48d06db69c36a98319dfe3254c2a936f3d Mon Sep 17 00:00:00 2001 From: axayjha Date: Thu, 15 Oct 2020 21:30:11 +0530 Subject: [PATCH] adding documentation and other enhancements --- dynamic_programming/word_break.cpp | 84 +++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 8 deletions(-) diff --git a/dynamic_programming/word_break.cpp b/dynamic_programming/word_break.cpp index 6de8eaf8d..e13dfff55 100644 --- a/dynamic_programming/word_break.cpp +++ b/dynamic_programming/word_break.cpp @@ -36,47 +36,115 @@ using std::string; using std::unordered_set; using std::vector; +/** + * @brief Solution class + */ class Solution { public: - bool exists(const string &s, const unordered_set &strSet) { - return strSet.find(s) != strSet.end(); + /** + * @brief Function that checks if the string passed in param is present in + * the the unordered_set passed + * + * @param str the string to be searched + * @param strSet unordered set of string, that is to be looked into + * @returns bool, true if str is present in strSet + */ + bool exists(const string &str, const unordered_set &strSet) { + return strSet.find(str) != strSet.end(); } + /** + * @brief Function that checks if the string passed in param can be + * segmented from position 'pos', and then correctly go on to segment the + * rest of the string correctly as well to reach a solution + * + * @param s the complete string to be segmented + * @param strSet unordered set of string, that is to be used as the + * reference dictionary + * @param pos the index value at which we will segment string and test + * further if it is correctly segmented at pos + * @param dp the vector to memoize solution for each position + * @returns bool, true if str is present in strSet + */ bool check(const string &s, const unordered_set &strSet, int pos, vector *dp) { if (pos == s.length()) { + // if we have reached till the end of the string, means we have + // segmented throughout correctly hence we have a solution, thus + // returning true return true; } if (dp->at(pos) != INT_MAX) { + // if dp[pos] is not INT_MAX, means we must have saved a solution + // for the position pos; then return if the solution at pos is true + // or not return dp->at(pos) == 1; } - string wordTillNow = ""; + string wordTillNow = + ""; // string to save the prefixes of word till different positons + for (int i = pos; i < s.length(); i++) { - wordTillNow += string(1, s[i]); + // Loop starting from pos to end, to check valid set of + // segmentations if any + wordTillNow += + string(1, s[i]); // storing the prefix till the position i + + // if the prefix till current position is present in the dictionary + // and the remaining substring can also be segmented legally, then + // set solution at position pos in the memo, and return true if (exists(wordTillNow, strSet) and check(s, strSet, i + 1, dp)) { dp->at(pos) = 1; return true; } } - dp->at(pos) = 0; - return false; + // if function has still not returned, then there must be no legal + // segmentation possible after segmenting at pos + dp->at(pos) = 0; // so set solution at pos as false + return false; // and return no solution at position pos } + /** + * @brief Function that checks if the string passed in param can be + * segmented into the strings present in the vector. + * In others words, it checks if any permutation of strings in + * the vector can be concatenated to form the final string. + * + * @param s the complete string to be segmented + * @param wordDict a vector of words to be used as dictionary to look into + * @returns bool, true if s can be + */ bool wordBreak(const string &s, const vector &wordDict) { + // unordered set to store words in the dictionary for contant time + // search unordered_set strSet; for (const auto &s : wordDict) { strSet.insert(s); } - + // a vector to be used for memoization, whose value at index i will + // tell if the string s can be segmented (correctly) at position i. + // initializing it with INT_MAX (which will denote no solution) vector dp(s.length(), INT_MAX); + + // calling check method with position = 0, to check from left + // from where can be start segmenting the complete string in correct + // manner return check(s, strSet, 0, &dp); } }; +/** + * @brief Main function + * @returns 0 on exit + */ int main() { + // the complete string const string s = "applepenapple"; + // the dictionary to be used const vector wordDict = {"apple", "pen"}; + + // should return true, as applepenapple can be segmented as apple + pen + + // apple cout << Solution().wordBreak(s, wordDict) << endl; -} \ No newline at end of file +}