Related Articles

# Count ways to increase LCS length of two strings by one

• Difficulty Level : Hard
• Last Updated : 28 Oct, 2020

Given two strings of lower alphabet characters, we need to find the number of ways to insert a character in the first string such that length of LCS of both strings increases by one.

Examples:

```Input : str1 = “abab”, str2 = “abc”
Output : 3
LCS length of given two strings is 2.
There are 3 ways of insertion in str1,
to increase the LCS length by one which
are enumerated below,
str1 = “abcab”    str2 = “abc”  LCS length = 3
str1 = “abacb”    str2 = “abc”  LCS length = 3
str1 = “ababc”    str2 = “abc”  LCS length = 3

Input : str1 = “abcabc”, str2 = “abcd”
Output : 4

```

The idea is try all 26 possible characters at each position of first string, if length of str1 is m then a new character can be inserted in (m + 1) positions, now suppose at any time character c is inserted at ith position in str1 then we will match it with all positions having character c in str2. Suppose one such position is j, then for total LCS length to be one more than previous, below condition should satisfy,

```LCS(str1[1, m], str2[1, n]) = LCS(str1[1, i],  str2[1, j-1]) +
LCS(str1[i+1, m], str2[j+1, n])

```

Above equation states that sum of LCS of the suffix and prefix substrings at inserted character must be same as total LCS of strings, so that when the same character is inserted in first string it will increase the length of LCS by one.
In below code two 2D arrays, lcsl and lcsr are used for storing LCS of prefix and suffix of strings respectively. Method for filling these 2D arrays can be found here

Please see below code for better understanding,

## C++

 `// C++ program to get number of ways to increase``// LCS by 1``#include ``using` `namespace` `std;` `#define M 26` `// Utility method to get integer position of lower``// alphabet character``int` `toInt(``char` `ch)``{``    ``return` `(ch - ``'a'``);``}` `// Method returns total ways to increase LCS length by 1``int` `waysToIncreaseLCSBy1(string str1, string str2)``{``    ``int` `m = str1.length(), n = str2.length();` `    ``// Fill positions of each character in vector``    ``vector<``int``> position[M];``    ``for` `(``int` `i = 1; i <= n; i++)``        ``position[toInt(str2[i-1])].push_back(i);` `    ``int` `lcsl[m + 2][n + 2];``    ``int` `lcsr[m + 2][n + 2];` `    ``// Initializing 2D array by 0 values``    ``for` `(``int` `i = 0; i <= m+1; i++)``        ``for` `(``int` `j = 0; j <= n + 1; j++)``            ``lcsl[i][j] = lcsr[i][j] = 0;` `    ``// Filling LCS array for prefix substrings``    ``for` `(``int` `i = 1; i <= m; i++)``    ``{``        ``for` `(``int` `j = 1; j <= n; j++)``        ``{``            ``if` `(str1[i-1] == str2[j-1])``                ``lcsl[i][j] = 1 + lcsl[i-1][j-1];``            ``else``                ``lcsl[i][j] = max(lcsl[i-1][j],``                                ``lcsl[i][j-1]);``        ``}``    ``}` `    ``// Filling LCS array for suffix substrings``    ``for` `(``int` `i = m; i >= 1; i--)``    ``{``        ``for` `(``int` `j = n; j >= 1; j--)``        ``{``            ``if` `(str1[i-1] == str2[j-1])``                ``lcsr[i][j] = 1 + lcsr[i+1][j+1];``            ``else``                ``lcsr[i][j] = max(lcsr[i+1][j],``                                 ``lcsr[i][j+1]);``        ``}``    ``}` `    ``// Looping for all possible insertion positions``    ``// in first string``    ``int` `ways = 0;``    ``for` `(``int` `i=0; i<=m; i++)``    ``{``        ``// Trying all possible lower case characters``        ``for` `(``char` `c=``'a'``; c<=``'z'``; c++)``        ``{``            ``// Now for each character, loop over same``            ``// character positions in second string``            ``for` `(``int` `j=0; j

## Java

 `// Java program to get number of ways to increase``// LCS by 1``import` `java.util.*;` `class` `GFG``{``    ``static` `int` `M = ``26``;` `    ``// Method returns total ways to increase``    ``// LCS length by 1``    ``static` `int` `waysToIncreaseLCSBy1(String str1,``                                    ``String str2)``    ``{``        ``int` `m = str1.length(), n = str2.length();` `        ``// Fill positions of each character in vector``        ``Vector[] position = ``new` `Vector[M];``        ``for` `(``int` `i = ``0``; i < M; i++)``            ``position[i] = ``new` `Vector<>();` `        ``for` `(``int` `i = ``1``; i <= n; i++)``            ``position[str2.charAt(i - ``1``) - ``'a'``].add(i);` `        ``int``[][] lcsl = ``new` `int``[m + ``2``][n + ``2``];``        ``int``[][] lcsr = ``new` `int``[m + ``2``][n + ``2``];` `        ``// Initializing 2D array by 0 values``        ``for` `(``int` `i = ``0``; i <= m + ``1``; i++)``            ``for` `(``int` `j = ``0``; j <= n + ``1``; j++)``                ``lcsl[i][j] = lcsr[i][j] = ``0``;` `        ``// Filling LCS array for prefix substrings``        ``for` `(``int` `i = ``1``; i <= m; i++)``        ``{``            ``for` `(``int` `j = ``1``; j <= n; j++)``            ``{``                ``if` `(str1.charAt(i - ``1``) == str2.charAt(j - ``1``))``                    ``lcsl[i][j] = ``1` `+ lcsl[i - ``1``][j - ``1``];``                ``else``                    ``lcsl[i][j] = Math.max(lcsl[i - ``1``][j],``                                          ``lcsl[i][j - ``1``]);``            ``}``        ``}` `        ``// Filling LCS array for suffix substrings``        ``for` `(``int` `i = m; i >= ``1``; i--)``        ``{``            ``for` `(``int` `j = n; j >= ``1``; j--)``            ``{``                ``if` `(str1.charAt(i - ``1``) == str2.charAt(j - ``1``))``                    ``lcsr[i][j] = ``1` `+ lcsr[i + ``1``][j + ``1``];``                ``else``                    ``lcsr[i][j] = Math.max(lcsr[i + ``1``][j],``                                          ``lcsr[i][j + ``1``]);``            ``}``        ``}` `        ``// Looping for all possible insertion positions``        ``// in first string``        ``int` `ways = ``0``;``        ``for` `(``int` `i = ``0``; i <= m; i++)``        ``{` `            ``// Trying all possible lower case characters``            ``for` `(``char` `d = ``0``; d < ``26``; d++)``            ``{` `                ``// Now for each character, loop over same``                ``// character positions in second string``                ``for` `(``int` `j = ``0``; j < position[d].size(); j++)``                ``{``                    ``int` `p = position[d].elementAt(j);` `                    ``// If both, left and right substrings make``                    ``// total LCS then increase result by 1``                    ``if` `(lcsl[i][p - ``1``] +``                        ``lcsr[i + ``1``][p + ``1``] == lcsl[m][n])``                        ``ways++;``                ``}``            ``}``        ``}``        ``return` `ways;``    ``}` `    ``// Driver Code``    ``public` `static` `void` `main(String[] args)``    ``{``        ``String str1 = ``"abcabc"``;``        ``String str2 = ``"abcd"``;``        ``System.out.println(waysToIncreaseLCSBy1(str1, str2));``    ``}``}` `// This code is contributed by``// sanjeev2552`

## Python3

 `# Python3 program to get number of ways to increase``# LCS by 1` `M ``=` `26` `# Method returns total ways to increase LCS length by 1``def` `waysToIncreaseLCSBy1(str1, str2):``    ``m ``=` `len``(str1)``    ``n ``=` `len``(str2)` `    ``# Fill positions of each character in vector``    ``# vector position[M];``    ``position ``=` `[[] ``for` `i ``in` `range``(M)]``    ``for` `i ``in` `range``(``1``, n``+``1``, ``1``):``        ``position[``ord``(str2[i``-``1``])``-``97``].append(i)` `    ``# Initializing 2D array by 0 values``    ``lcsl ``=` `[[``0` `for` `i ``in` `range``(n``+``2``)] ``for` `j ``in` `range``(m``+``2``)]``    ``lcsr ``=` `[[``0` `for` `i ``in` `range``(n``+``2``)] ``for` `j ``in` `range``(m``+``2``)]` `    ``# Filling LCS array for prefix substrings``    ``for` `i ``in` `range``(``1``, m``+``1``, ``1``):``        ``for` `j ``in` `range``(``1``, n``+``1``,``1``):``            ``if` `(str1[i``-``1``] ``=``=` `str2[j``-``1``]):``                ``lcsl[i][j] ``=` `1` `+` `lcsl[i``-``1``][j``-``1``]``            ``else``:``                ``lcsl[i][j] ``=` `max``(lcsl[i``-``1``][j],``                                ``lcsl[i][j``-``1``])` `    ``# Filling LCS array for suffix substrings``    ``for` `i ``in` `range``(m, ``0``, ``-``1``):``        ``for` `j ``in` `range``(n, ``0``, ``-``1``):``            ``if` `(str1[i``-``1``] ``=``=` `str2[j``-``1``]):``                ``lcsr[i][j] ``=` `1` `+` `lcsr[i``+``1``][j``+``1``]``            ``else``:``                ``lcsr[i][j] ``=` `max``(lcsr[i``+``1``][j],``                                ``lcsr[i][j``+``1``])` `        ``# Looping for all possible insertion positions``        ``# in first string``    ``ways ``=` `0``    ``for` `i ``in` `range``(``0``, m``+``1``,``1``):``        ``# Trying all possible lower case characters``        ``for` `C ``in` `range``(``0``, ``26``,``1``):``            ``# Now for each character, loop over same``            ``# character positions in second string``            ``for` `j ``in` `range``(``0``, ``len``(position[C]),``1``):``                ``p ``=` `position[C][j]` `                ``# If both, left and right substrings make``                ``# total LCS then increase result by 1``                ``if` `(lcsl[i][p``-``1``] ``+` `lcsr[i``+``1``][p``+``1``] ``=``=` `lcsl[m][n]):``                    ``ways ``+``=` `1``    ``return` `ways`  `# Driver code to test above methods``str1 ``=` `"abcabc"``str2 ``=` `"abcd"``print``(waysToIncreaseLCSBy1(str1, str2))` `# This code is contributed by ankush_953`

## C#

 `// C# program to get number of ways``// to increase LCS by 1``using` `System;``using` `System.Collections.Generic;` `class` `GFG{``    ` `static` `int` `M = 26;` `// Method returns total ways to increase``// LCS length by 1``static` `int` `waysToIncreaseLCSBy1(String str1,``                                ``String str2)``{``    ``int` `m = str1.Length, n = str2.Length;` `    ``// Fill positions of each character in vector``    ``List<``int``>[] position = ``new` `List<``int``>[M];``    ``for``(``int` `i = 0; i < M; i++)``        ``position[i] = ``new` `List<``int``>();` `    ``for``(``int` `i = 1; i <= n; i++)``        ``position[str2[i - 1] - ``'a'``].Add(i);` `    ``int``[,] lcsl = ``new` `int``[m + 2, n + 2];``    ``int``[,] lcsr = ``new` `int``[m + 2, n + 2];` `    ``// Initializing 2D array by 0 values``    ``for``(``int` `i = 0; i <= m + 1; i++)``        ``for``(``int` `j = 0; j <= n + 1; j++)``            ``lcsl[i, j] = lcsr[i, j] = 0;` `    ``// Filling LCS array for prefix substrings``    ``for``(``int` `i = 1; i <= m; i++)``    ``{``        ``for``(``int` `j = 1; j <= n; j++)``        ``{``            ``if` `(str1[i - 1] == str2[j - 1])``                ``lcsl[i, j] = 1 + lcsl[i - 1, j - 1];``            ``else``                ``lcsl[i, j] = Math.Max(lcsl[i - 1, j],``                                      ``lcsl[i, j - 1]);``        ``}``    ``}` `    ``// Filling LCS array for suffix substrings``    ``for``(``int` `i = m; i >= 1; i--)``    ``{``        ``for``(``int` `j = n; j >= 1; j--)``        ``{``            ``if` `(str1[i - 1] == str2[j - 1])``                ``lcsr[i, j] = 1 + lcsr[i + 1, j + 1];``            ``else``                ``lcsr[i, j] = Math.Max(lcsr[i + 1, j],``                                      ``lcsr[i, j + 1]);``        ``}``    ``}` `    ``// Looping for all possible insertion``    ``// positions in first string``    ``int` `ways = 0;``    ``for``(``int` `i = 0; i <= m; i++)``    ``{``        ` `        ``// Trying all possible lower``        ``// case characters``        ``for``(``int` `d = 0; d < 26; d++)``        ``{``            ` `            ``// Now for each character, loop over same``            ``// character positions in second string``            ``for``(``int` `j = 0; j < position[d].Count; j++)``            ``{``                ``int` `p = position[d][j];` `                ``// If both, left and right substrings make``                ``// total LCS then increase result by 1``                ``if` `(lcsl[i, p - 1] +``                    ``lcsr[i + 1, p + 1] == lcsl[m, n])``                    ``ways++;``            ``}``        ``}``    ``}``    ``return` `ways;``}` `// Driver Code``public` `static` `void` `Main(String[] args)``{``    ``String str1 = ``"abcabc"``;``    ``String str2 = ``"abcd"``;``    ` `    ``Console.WriteLine(waysToIncreaseLCSBy1(str1, str2));``}``}` `// This code is contributed by Princi Singh`

Output:

```4

```

Time Complexity : O(mn)
Auxiliary Space : O(mn)

This article is contributed by Utkarsh Trivedi. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.