/** * @file * @brief Implementation of Abbrievation * (https://www.hackerrank.com/challenges/abbr/problem) * * @details * Given two strings, a and b, determine if it's possible to make a equal to * b You can perform the following operations on the string a: * 1. Capitalize zero or more of a's lowercase letters. * 2. Delete all of the remaining lowercase letters in a. * * ##Algorithm * The idea is in the problem statement itself: iterate through characters of * string a and b (for character indexes i and j respectively): * 1. If a[i] and b[j] are equal, then move to next position * 2. If a[i] is lowercase of b[j], then explore two possibilities: * a. Capitalize or * a. Skip a[i] * 3. If the a[i] is not uppercase, just discard the char, else return false * * Time Complexity (O(|a|*|b|)) where |a| => length of string * @author Ashish Daulatabad (https://github.com/AshishYUO) */ #include #include #include #include /** * @namespace dynamic_programming * @brief Dynamic Programming Algorithms */ namespace dynamic_programming { /** * @namespace Knapsack * @brief Implementation of Abbreivation problem */ namespace abbreviation { /** * (recursive dp function) https://www.hackerrank.com/challenges/abbr/problem * Returns whether s can be converted to t with following rules: * a. Capitalize zero or more of a's lowercase letters from string s * b. remove all other lowercase letters from string s * @param dp: memo as parameter to store the result * @param v: visited boolean to check if the result is already computed * @param s: given string * @param t: resultant abbreivated string * @param i: start of string s * @param j: start of string j * @returns bool whether s can be converted to t */ bool abbreviation_recursion(std::vector> *memo, std::vector> *visited, const std::string &s, const std::string &t, int i = 0, int j = 0) { bool ans = memo->at(i).at(j); if (i == s.size() && j == t.size()) { return true; } else if (i == s.size() && j != t.size()) { // result t is not converted, return false return false; } else if (!visited->at(i).at(j)) { /** * (s[i] == t[j]): if s char at position i is equal to t char at * position j, then s character is a capitalized one, move on to next * character * s[i] - 32 == t[j]: if s[i] character is lowercase of t[j] then * explore two possibilites: * 1. convert it to capitalized and move both to next pointer (i + 1, j * + 1) * 2. Discard the character (s[i]) and move to next char (i + 1, j) */ if (s[i] == t[j]) { ans = abbreviation_recursion(memo, visited, s, t, i + 1, j + 1); } else if (s[i] - 32 == t[j]) { ans = abbreviation_recursion(memo, visited, s, t, i + 1, j + 1) || abbreviation_recursion(memo, visited, s, t, i + 1, j); } else { // if s[i] is uppercase, then cannot be converted, return false // else s[i] is lowercase, only option is to discard this character if (s[i] >= 'A' && s[i] <= 'Z') { ans = false; } else { ans = abbreviation_recursion(memo, visited, s, t, i + 1, j); } } } (*memo)[i][j] = ans; (*visited)[i][j] = true; return (*memo)[i][j]; } /** * (iterative dp function) https://www.hackerrank.com/challenges/abbr/problem: * Returns whether s can be converted to t with following rules: * a. Capitalize zero or more of a's lowercase letters from string s * b. remove all other lowercase letters from string s * @param s: string * @param t: resultant string * @returns boolean (true or false) whether s can be converted to t */ bool abbreviation(const std::string &s, const std::string &t) { std::vector> memo(s.size() + 1, std::vector(t.size() + 1, 0)); for (int i = 0; i <= s.size(); ++i) memo[i][0] = true; for (int i = 1; i <= t.size(); ++i) memo[0][i] = false; for (int i = 1; i <= s.size(); ++i) { for (int j = 1; j <= t.size(); ++j) { if (s[i - 1] == t[j - 1]) { memo[i][j] = memo[i - 1][j - 1]; } else if (s[i - 1] - 32 == t[j - 1]) { memo[i][j] = (memo[i - 1][j - 1] || memo[i - 1][j]); } else { if (s[i - 1] >= 'A' && s[i - 1] <= 'Z') { memo[i][j] = false; } else { memo[i][j] = memo[i - 1][j]; } } } } return memo.back().back(); } } // namespace abbreviation } // namespace dynamic_programming static void test() { std::string s = "daBcd", t = "ABC"; std::vector> memo(s.size() + 1, std::vector(t.size() + 1, 0)), visited(s.size() + 1, std::vector(t.size() + 1, 0)); assert(dynamic_programming::abbreviation::abbreviation_recursion( &memo, &visited, s, t) == true); assert(dynamic_programming::abbreviation::abbreviation(s, t) == true); s = "XXVVnDEFYgYeMXzWINQYHAQKKOZEYgSRCzLZAmUYGUGILjMDET"; t = "XXVVDEFYYMXWINQYHAQKKOZEYSRCLZAUYGUGILMDETQVWU"; memo = std::vector>(s.size() + 1, std::vector(t.size() + 1, 0)); visited = std::vector>( s.size() + 1, std::vector(t.size() + 1, 0)); assert(dynamic_programming::abbreviation::abbreviation_recursion( &memo, &visited, s, t) == false); assert(dynamic_programming::abbreviation::abbreviation(s, t) == false); s = "DRFNLZZVHLPZWIupjwdmqafmgkg"; t = "DRFNLZZVHLPZWI"; memo = std::vector>(s.size() + 1, std::vector(t.size() + 1, 0)); visited = std::vector>( s.size() + 1, std::vector(t.size() + 1, 0)); assert(dynamic_programming::abbreviation::abbreviation_recursion( &memo, &visited, s, t) == true); assert(dynamic_programming::abbreviation::abbreviation(s, t) == true); } int main() { test(); return 0; }