class Solution { public: int memo[1001][1001]; // Backward recursion (m, n) -> (0, 0) int lcs1 (string s1, string s2, int m, int n) { if (m == -1 || n == -1) return 0; if (memo[m][n] != -1) return memo[m][n]; int ans = 0; if (s1[m] == s2[n]) ans = 1 + lcs1(s1, s2, m-1, n-1); else ans = max(lcs1(s1, s2, m-1, n), lcs1(s1, s2, m, n-1)); memo[m][n] = ans; return ans; } // Forward recursion (0, 0) -> (m, n) int lcs2 (string s1, string s2, int i, int j, int m, int n) { if (i == m || j == n) return 0; if (memo[i][j] != -1) return memo[i][j]; int a, b, c; a = b = c = 0; int ans = 0; if (s1[i] == s2[j]) { if (memo[i+1][j+1] != -1) a = memo[i+1][j+1]; else { a = lcs2(s1, s2, i+1, j+1, m, n); memo[i+1][j+1] = a; } ans = 1 + a; } else { if (memo[i][j+1] != -1) b = memo[i][j+1]; else { b = lcs2(s1, s2, i, j+1, m, n); memo[i][j+1] = b; } if (memo[i+1][j] != -1) c = memo[i+1][j]; else { c = lcs2(s1, s2, i+1, j, m, n); memo[i+1][j] = c; } ans = max(b, c); } memo[i][j] = ans; return ans; } int lcs(string s1, string s2) { int m = s1.size(); int n = s2.size(); int dp[m+1][n+1]; for (int i = 0; i <= m; i++) for (int j = 0; j <= n; j++) dp[i][j] = 0; for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (s1[i-1] == s2[j-1]) dp[i][j] = 1 + dp[i-1][j-1]; else dp[i][j] = max(dp[i-1][j], dp[i][j-1]); } } return dp[m][n]; } int longestCommonSubsequence(string text1, string text2) { // for (int i = 0; i <= text1.size(); i++) // for (int j = 0; j <= text2.size(); j++) // memo[i][j] = -1; // return lcs1(text1, text2, text1.size()-1, text2.size()-1); // return lcs2(text1, text2, 0, 0, text1.size(), text2.size()); return lcs(text1, text2); } };