Files
C-Plus-Plus/dynamic_programming/abbreviation.cpp
Ashish Bhanu Daulatabad 232d4f5eba Refactoring code
2021-03-07 11:01:11 +05:30

165 lines
6.3 KiB
C++

/**
* @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 <cassert>
#include <iostream>
#include <string>
#include <vector>
/**
* @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<std::vector<bool>> *memo,
std::vector<std::vector<bool>> *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<std::vector<bool>> memo(s.size() + 1,
std::vector<bool>(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<std::vector<bool>> memo(s.size() + 1,
std::vector<bool>(t.size() + 1, 0)),
visited(s.size() + 1, std::vector<bool>(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<std::vector<bool>>(s.size() + 1,
std::vector<bool>(t.size() + 1, 0));
visited = std::vector<std::vector<bool>>(
s.size() + 1, std::vector<bool>(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<std::vector<bool>>(s.size() + 1,
std::vector<bool>(t.size() + 1, 0));
visited = std::vector<std::vector<bool>>(
s.size() + 1, std::vector<bool>(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;
}