forked from TheAlgorithms/C-Plus-Plus
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathshortest_common_supersequence.cpp
179 lines (156 loc) · 5.22 KB
/
shortest_common_supersequence.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/**
* @file
* @brief SCS is a string Z which is the shortest supersequence of strings X and Y (may not be continuous in Z, but order is maintained).
*
* @details
* The idea is to use lookup table method as used in LCS.
* For example: example 1:-
* X: 'ABCXYZ', Y: 'ABZ' then Z will be 'ABCXYZ' (y is not continuous but in order)
*
* For example: example 2:-
* X: 'AGGTAB', Y: 'GXTXAYB' then Z will be 'AGGXTXAYB'
* @author [Ridhish Jain](https://github.com/ridhishjain)
* @see more on [SCS](https://en.wikipedia.org/wiki/Shortest_common_supersequence_problem)
* @see related problem [Leetcode](https://leetcode.com/problems/shortest-common-supersequence/)
*/
// header files
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cassert>
/**
* @namespace dynamic_programming
* @brief Dynamic Programming algorithms
*/
namespace dynamic_programming {
/**
* @namespace shortest_common_supersequence
* @brief Shortest Common Super Sequence algorithm
*/
namespace shortest_common_supersequence {
/**
* Function implementing Shortest Common Super-Sequence algorithm using look-up table method.
* @param str1 first string 'X'
* @param str2 second string 'Y'
* @returns string 'Z', superSequence of X and Y
*/
std::string scs(const std::string &str1, const std::string &str2) {
// Edge cases
// If either str1 or str2 or both are empty
if(str1.empty() && str2.empty()) {
return "";
}
else if(str1.empty()) {
return str2;
}
else if(str2.empty()) {
return str1;
}
// creating lookup table
std::vector <std::vector <int>> lookup(str1.length() + 1, std::vector <int> (str2.length() + 1, 0));
for(int i=1; i <= str1.length(); i++) {
for(int j=1; j <= str2.length(); j++) {
if(str1[i-1] == str2[j-1]) {
lookup[i][j] = lookup[i-1][j-1] + 1;
}
else {
lookup[i][j] = std::max(lookup[i-1][j], lookup[i][j-1]);
}
}
}
// making supersequence
// i and j are initially pointed towards end of strings
// Super-sequence will be constructed backwards
int i=str1.length();
int j=str2.length();
std::string s;
while(i>0 && j>0) {
// If the characters at i and j of both strings are same
// We only need to add them once in s
if(str1[i-1] == str2[j-1]) {
s.push_back(str1[i-1]);
i--;
j--;
}
// otherwise we check lookup table for recurrences of characters
else {
if(lookup[i-1][j] > lookup[i][j-1]) {
s.push_back(str1[i-1]);
i--;
}
else {
s.push_back(str2[j-1]);
j--;
}
}
}
// copying remaining elements
// if j becomes 0 before i
while(i > 0) {
s.push_back(str1[i-1]);
i--;
}
// if i becomes 0 before j
while(j > 0) {
s.push_back(str2[j-1]);
j--;
}
// As the super sequence is constructd backwards
// reversing the string before returning gives us the correct output
reverse(s.begin(), s.end());
return s;
}
} // namespace shortest_common_supersequence
} // namespace dynamic_programming
/**
* Test Function
* @return void
*/
static void test() {
// custom input vector
std::vector <std::vector <std::string>> scsStrings {
{"ABCXYZ", "ABZ"},
{"ABZ", "ABCXYZ"},
{"AGGTAB", "GXTXAYB"},
{"X", "Y"},
};
// calculated output vector by scs function
std::vector <std::string> calculatedOutput(4, "");
int i=0;
for(auto & scsString : scsStrings) {
calculatedOutput[i] = dynamic_programming::shortest_common_supersequence::scs(
scsString[0], scsString[1]
);
i++;
}
// expected output vector acc to problem statement
std::vector <std::string> expectedOutput {
"ABCXYZ",
"ABCXYZ",
"AGGXTXAYB",
"XY"
};
// 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 < scsStrings.size(); i++) {
assert(expectedOutput[i] == calculatedOutput[i]);
}
std::cout << "All tests passed successfully!\n";
return;
}
/** Main function (driver code)*/
int main() {
// test for implementation
test();
// user input
std::string s1, s2;
std::cin >> s1;
std::cin >> s2;
std::string ans;
// user output
ans = dynamic_programming::shortest_common_supersequence::scs(s1, s2);
std::cout << ans;
return 0;
}