In this post i am going to discuss problems that you can solve using LCS. Recently i solved question about DP on string and i think there are more problems that you can solve only using LCS with a little bit of change.
A subsequence of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.
Example :
Input: text1 = "abcdgh", text2 = "abedfhq"
Output: 4
Explanation: The longest common subsequence is "abdh" and its length is 4.here is the pseudo code for that
int LCS(string s, string t, int n, int m)
{
// n = length of s
// m = length of t
//Base condition
if(n==0 || m == 0)
return 0;
if(s[n-1] == t[m-1])
return 1 + LCS(s,t,n-1,m-1)
else
return max(LCS(s,t,n,m-1), LCS(s,t,n-1,m))Let's understand Base case:

As s[n] != t[m]
and if s[n] != t[m]
HERE IS THE TABULATION CODE (i'm going to use this in all sol)
int longestCommonSubsequence(string text1, string text2) {
int n = text1.size();
int m = text2.size();
vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (text1[i - 1] == text2[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[n][m];
}if you solve Longest Common subsequence. you can pretty much solve Longest common substring.
Although it is not on the leetcode but here is the similar problem
Given two integer arrays nums1 and nums2, return the maximum length of a subarray that appears in both arrays.
Example :
Input: nums1 = [1,2,3,2,1], nums2 = [3,2,1,4,7]
Output: 3
Explanation: The repeated subarray with maximum length is [3,2,1].can you find the pattern ??
if(nums1[i-1] != nums2[j-1]),
the characters don’t match, therefore the consecutiveness of characters is broken. So we set the cell value (dp[i][j]) as 0.
if (nums1[i-1] == nums2[j-1]) matches we set its value to 1+dp[i-1][j-1]
we have to keep track of maximum length encounter because answer is max(dp[i][j])
int findLength(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size();
int m = nums2.size();
vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
int ans = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (nums1[i - 1] == nums2[j - 1]) {
dp[i][j] = 1 + dp[i - 1][j - 1];
ans = max(ans, dp[i][j]);
} else
dp[i][j] = 0;
}
}
return ans;
}Given a string s, find the longest palindromic subsequence's length in s.
A palindromic string is a string that is equal to its reverse.
Example :
Input: s = "bbbab"
Output: 4
Explanation: One possible longest palindromic subsequence is "bbbb".Let's rewrite the input
Input: s = "bbbab" t = "babbb"Now can you see it ??
Basically The longest palindromic subsequence of a string is the longest common subsequence of the given string and its reverse.
int longestPalindromeSubseq(string s) {
string a = s;
reverse(a.begin(), a.end());
int n = s.size();
vector<vector<int>> dp(n + 1, vector<int>(n + 1, 0));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (s[i - 1] == a[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[n][n];
}/
Below question is not on leetcode.(I solved it on another platform but i didn't remember which one)
convert string a into string b. you can do
Input: a = "heap" b = "pea"
Output: deletion : 2 insertion : 1for above example first we have to delete h and p from a so we have "ea" and then we can insert p to achive our string b.
can you find pattern??
see "ea" is what?? ----------> LCS
a = "heap" b = "pea"
minimum number of deletions = a.length – LCS
minimum number of Insertions minInsert = b.length – LCS
vector<pair> MinDelAndIns(string a, string b)
{
int n = a.length();
int m = b.length();
int LCS_length = LCS(a,b,n,m)
int delete = LCS - n;
int insert = LCS - m;
return {delete,insert}
}Now You can solve
In this question you also can replace charcter.
Given a string s. In one step you can insert any character at any index of the string.
Return the minimum number of steps to make s palindrome.
Input: s = "mbadm"
Output: 2
Explanation: String can be "mbdadbm" or "mdbabdm".Let's think it as before where we solve longest palindrome subsequence
Input: s = "mbadm" t = "mdabm"
Output: 2
Explanation: String can be "mbdadbm" or "mdbabdm".int minInsertions(string s) {
string st = s;
int n = s.size();
reverse(st.begin(), st.end());
vector<vector<int>> dp(n + 1, vector<int>(n + 1, 0));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (s[i - 1] == st[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 n - dp[n][n];
}Now if interviwer ask you what is the minimum number of deletion to make it a palindrom.
Given two strings s and t, return true if s is a subsequence of t, or false otherwise.
Example :
Input: s = "abc", t = "ahbgdc"
Output: trueCan you find a pattern??
You can also do this question by two pointer but this post is about LCS So guess what..
bool isSubsequence(string s, string t) {
int n = s.size();
int m = t.size();
vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
int ans = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (s[i - 1] == t[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[n][m] == n;
}** Example : **
Input: word1 = "sea", word2 = "eat"
Output: 2
Explanation: You need one step to make "sea" to "ea" and another step to make "eat" to "ea".int minDistance(string word1, string word2) {
int n = word1.size();
int m = word2.size();
vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (word1[i - 1] == word2[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 (n - dp[n][m]) + (m - dp[n][m]);
}Given two strings str1 and str2, return the shortest string that has both str1 and str2 as subsequences. If there are multiple valid strings, return any of them.
A string s is a subsequence of string t if deleting some number of characters from t (possibly 0) results in the string s.
Example :
Input: str1 = "abac", str2 = "cab"
Output: "cabac"
Explanation:
str1 = "abac" is a subsequence of "cabac" because we can delete the first "c".
str2 = "cab" is a subsequence of "cabac" because we can delete the last "ac".
The answer provided is the shortest such string that satisfies these properties.let's for simplacity we take simple example
Input: str1 = "leet", str2 = "ete"
Output: "leete"Can you use LCS here??
we have LCS in our answer as substring if you carefully notice..
"leete"
"cabac"
for answer of length part don't you think it is same as we did before.
let just say we add two string as it is "leetete" In this case we have our LCS 2 times and we want shortest length as our answer.
can we make a string such that LCS is there only one time and then we can add all remaining charcter from strings such that order is maintained.
Let's first find length of shortest common supersequence
ans = LCS + (A - LCS) + (B-LCS)
= A + B - LCS
string shortestCommonSupersequence(string str1, string str2) {
int n = str1.size();
int m = str2.size();
vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (str1[i - 1] == str2[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 n + m - dp[n][m];For printing shortest common supersequence you have to understand how to print LCS
This question is not on leetcode ( i didn't find it) but if it were than it would be in hard category..
For printing LCS we require our top-down table..
Example:

In the reconstruction process of the Longest Common Substring, each cell is examined. If the characters at positions i-1 and j-1 are equal, the character is added to the substring, and indices shift diagonally (↖).
If not, the algorithm moves to the cell with the larger value either to the left (←) or above (↑).
This continues until either i or j becomes non-positive, yielding the reconstructed Longest Common Substring.
string PrintLCS(string s, string t)
{
// LCS TABLE IS BUILT.
int i = n, j = m;
string ans = "";
while(i > 0 && j > 0)
{
if(s1[i-1] == s2[j-1])
{
ans.push_back(s1[i-1]);
i--;
j--;
}
else
{
if(dp[i][j-1] > dp[i-1][j])
{
j--;
}
else
i--;
}
}
// we have to reverse it because we did our traversal backwards so string is in reverse order.
reverse(ans.begin(), ans.end());
return ans;
}NOW Let's move back to our Question..
string shortestCommonSupersequence(string str1, string str2)
{
//OUR LCS TABLE IS BUILT.
string ans = "";
int i = n, j = m;
while(i > 0 && j > 0)
{
if(str1[i-1] == str2[j-1])
{
ans.push_back(str1[i-1]);
i--;
j--;
}
else
{
if(dp[i-1][j] > dp[i][j-1])
{
ans.push_back(str1[i-1]);
i--;
}
else
{
ans.push_back(str2[j-1]);
j--;
}
}
}
while(i > 0)
{
ans += str1[i-1];
i--;
}
while(j > 0)
{
ans += str2[j-1];
j--;
}
reverse(ans.begin(), ans.end());
return ans;
}You are given a string s of length n.. You are tasked to find the longest subsequence repeated in string s.
int LRS(string text1)
{
string text2 = text1;
int n = text1.size();
int m = text2.size();
vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (text1[i - 1] == text2[j - 1] && i != j ) {
dp[i][j] = 1 + dp[i - 1][j - 1];
} else
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
return dp[n][m];
}Hope this will help you a bit to ace your next coding interviews or competitive programming contest.
"Success is not final, failure is not fatal: It is the courage to continue that counts." - Winston Churchill
Any suggestions on improving Post are appreciated.
if you know similar question on this topic then comment.