-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlongestCommonSubsequence1143.cpp
113 lines (98 loc) · 3.35 KB
/
longestCommonSubsequence1143.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
#include <iostream>
#include <string>
int max(int a, int b)
{
return a > b ? a : b;
}
int total_calls;
int LCS(std::string str1, std::string str2, int str1Size, int str2Size)
{
total_calls++;
// base case or base cases
if (str1Size == 0 || str2Size == 0)
return 0;
// recursive cases
// if the last chars of the strings are a match, then we return 1 + lcs(str1.pop(), str2.pop())
if (str1[str1Size - 1] == str2[str2Size - 1])
return 1 + LCS(str1, str2, str1Size - 1, str2Size - 1);
else
return max(LCS(str1, str2, str1Size, str2Size - 1), LCS(str1, str2, str1Size - 1, str2Size));
// if they don't match
}
// to write the memoized version of LCS, we need the following:
// define a memo array to store answers to subproblem
// do the necessary initialization for the memo array
// every time when LCS function gets called,
// check if you already have the answer for the current subproblem in memo array
// if you do, return it, else call the function on that subproblem to compute the answer
// and store the answer to that subproblem before returning it
int LCS_memoized(std::string str1, std::string str2, int str1Size, int str2Size, int memo[100][100])
{
total_calls++;
if (str1Size == 0 || str2Size == 0)
return 0;
if (memo[str1Size][str2Size] != -1)
return memo[str1Size][str2Size];
if (str1[str1Size - 1] == str2[str2Size - 1])
{
memo[str1Size][str2Size] = 1 + LCS_memoized(str1, str2, str1Size - 1, str2Size - 1, memo);
return memo[str1Size][str2Size];
}
else
{
memo[str1Size][str2Size] = max(LCS_memoized(str1, str2, str1Size, str2Size - 1, memo), LCS_memoized(str1, str2, str1Size - 1, str2Size, memo));
return memo[str1Size][str2Size];
}
}
// dynamic programming implementation
int LCS_dp(std::string str1, std::string str2, int str1Size, int str2Size, int memo[100][100])
{
for (int row = 1; row <= str1Size; row++)
{
for (int col = 1; col <= str2Size; col++)
{
if (str1[row - 1] == str2[col - 1])
{
memo[row][col] = 1 + memo[row - 1][col - 1];
}
else
{
memo[row][col] = max(memo[row - 1][col], memo[row][col - 1]);
}
}
}
return memo[str1Size][str2Size];
}
int main()
{
std::string str1 = "babcdefde";
std::string str2 = "acde";
// to store the answer to subproblems to avoid recomputing them when needed
int memo[100][100]; // the size of the array is hard-coded
// needed initialization for memo array
for (int i = 0; i < 100; i++)
{
memo[0][i] = 0;
}
for (int i = 0; i < 100; i++)
{
memo[i][0] = 0;
}
// this part is only needed for memoized version
for (int row = 1; row < 100; row++)
{
for (int col = 1; col < 100; col++)
{
memo[row][col] = -1;
}
}
// recursive implementation
total_calls = 0;
std::cout << LCS(str1, str2, str1.size(), str2.size()) << " in calls " << total_calls << std::endl;
// memoized implementation
total_calls = 0;
std::cout << LCS_memoized(str1, str2, str1.size(), str2.size(), memo) << " in calls " << total_calls << std::endl;
// dynamic programming implementation
std::cout << LCS_dp(str1, str2, str1.size(), str2.size(), memo);
return 0;
}