Open In App

Count common subsequence in two strings

Last Updated : 08 Mar, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Given two string S and T. The task is to count the number of the common subsequence in S and T.

Examples:

Input : S = "ajblqcpdz", T = "aefcnbtdi" 
Output : 11 
Common subsequences are : { "a", "b", "c", "d", "ab", "bd", "ad", "ac", "cd", "abd", "acd" }

Input : S = "a", T = "ab" 
Output : 1

To find the number of common subsequences in two string, say S and T, we use Dynamic Programming by defining a 2D array dp[][], where dp[i][j] is the number of common subsequences in the string S[0...i-1] and T[0....j-1]. 

Now, we can define dp[i][j] as = dp[i][j-1] + dp[i-1][j] + 1, when S[i-1] is equal to T[j-1] 
This is because when S[i-1] == S[j-1], using the above fact all the previous common sub-sequences are doubled as they get appended by one more character. Both dp[i][j-1] and dp[i-1][j] contain dp[i-1][j-1] and hence it gets added two times in our recurrence which takes care of doubling of count of all previous common sub-sequences. Addition of 1 in recurrence is for the latest character match : common sub-sequence made up of s1[i-1] and s2[j-1]  = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1], when S[i-1] is not equal to T[j-1] 
Here we subtract dp[i-1][j-1] once because it is present in both dp[i][j - 1] and dp[i - 1][j] and gets added twice.

Implementation:

C++
// C++ program to count common subsequence in two strings
#include <bits/stdc++.h>
using namespace std;

// return the number of common subsequence in
// two strings
int CommonSubsequencesCount(string s, string t)
{
    int n1 = s.length();
    int n2 = t.length();
    int dp[n1+1][n2+1];

    for (int i = 0; i <= n1; i++) {
        for (int j = 0; j <= n2; j++) {
            dp[i][j] = 0;
        }
    }

    // for each character of S
    for (int i = 1; i <= n1; i++) {

        // for each character in T
        for (int j = 1; j <= n2; j++) {

            // if character are same in both 
            // the string
            if (s[i - 1] == t[j - 1]) 
                dp[i][j] = 1 + dp[i][j - 1] + dp[i - 1][j];            
            else 
                dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - 
                                        dp[i - 1][j - 1];            
        }
    }

    return dp[n1][n2];
}

// Driver Program
int main()
{
    string s = "ajblqcpdz";
    string t = "aefcnbtdi";

    cout << CommonSubsequencesCount(s, t) << endl;
    return 0;
}
Java
// Java program to count common subsequence in two strings
public class GFG {
    
    // return the number of common subsequence in 
    // two strings 
    static int CommonSubsequencesCount(String s, String t) 
    { 
        int n1 = s.length(); 
        int n2 = t.length(); 
        int dp[][] = new int [n1+1][n2+1]; 
        char ch1,ch2 ;
      
        for (int i = 0; i <= n1; i++) { 
            for (int j = 0; j <= n2; j++) { 
                dp[i][j] = 0; 
            } 
        } 
      
        // for each character of S 
        for (int i = 1; i <= n1; i++) { 
      
            // for each character in T 
            for (int j = 1; j <= n2; j++) { 
                
                ch1 = s.charAt(i - 1);
                ch2 = t.charAt(j - 1);
                
                // if character are same in both  
                // the string                 
                if (ch1 == ch2)  
                    dp[i][j] = 1 + dp[i][j - 1] + dp[i - 1][j];             
                else 
                    dp[i][j] = dp[i][j - 1] + dp[i - 1][j] -  
                                            dp[i - 1][j - 1];             
            } 
        } 
      
        return dp[n1][n2]; 
    } 
    // Driver code 
    public static void main (String args[]){
        
          String s = "ajblqcpdz"; 
          String t = "aefcnbtdi"; 
          
        System.out.println(CommonSubsequencesCount(s, t)); 
          
    }

// This code is contributed by ANKITRAI1
}
C#
// C# program to count common 
// subsequence in two strings
using System;

class GFG 
{

// return the number of common 
// subsequence in two strings 
static int CommonSubsequencesCount(string s, 
                                   string t) 
{ 
    int n1 = s.Length; 
    int n2 = t.Length; 
    int[,] dp = new int [n1 + 1, n2 + 1]; 
    
    for (int i = 0; i <= n1; i++) 
    { 
        for (int j = 0; j <= n2; j++) 
        { 
            dp[i, j] = 0; 
        } 
    } 
    
    // for each character of S 
    for (int i = 1; i <= n1; i++)
    { 
    
        // for each character in T 
        for (int j = 1; j <= n2; j++)
        {
            
            // if character are same in 
            // both the string                 
            if (s[i - 1] == t[j - 1]) 
                dp[i, j] = 1 + dp[i, j - 1] +
                               dp[i - 1, j];             
            else
                dp[i, j] = dp[i, j - 1] + 
                           dp[i - 1, j] - 
                           dp[i - 1, j - 1];             
        } 
    } 
    
    return dp[n1, n2]; 
} 

// Driver code 
public static void Main ()
{
    string s = "ajblqcpdz"; 
    string t = "aefcnbtdi"; 
        
    Console.Write(CommonSubsequencesCount(s, t)); 
}
}

// This code is contributed
// by ChitraNayal
JavaScript
<script>

// Javascript program to count common subsequence in two strings

// return the number of common subsequence in
// two strings
function CommonSubsequencesCount(s, t)
{
    var n1 = s.length;
    var n2 = t.length;
    var dp = Array.from(Array(n1+1), ()=> Array(n2+1));

    for (var i = 0; i <= n1; i++) {
        for (var j = 0; j <= n2; j++) {
            dp[i][j] = 0;
        }
    }

    // for each character of S
    for (var i = 1; i <= n1; i++) {

        // for each character in T
        for (var j = 1; j <= n2; j++) {

            // if character are same in both 
            // the string
            if (s[i - 1] == t[j - 1]) 
                dp[i][j] = 1 + dp[i][j - 1] + dp[i - 1][j];            
            else 
                dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - 
                                        dp[i - 1][j - 1];            
        }
    }

    return dp[n1][n2];
}

// Driver Program
var s = "ajblqcpdz";
var t = "aefcnbtdi";
document.write( CommonSubsequencesCount(s, t));


</script>
PHP
<?php
// PHP program to count common subsequence
// in two strings

// return the number of common subsequence
// in two strings
function CommonSubsequencesCount($s, $t)
{
    $n1 = strlen($s);
    $n2 = strlen($t);
    $dp = array();

    for ($i = 0; $i <= $n1; $i++) 
    {
        for ($j = 0; $j <= $n2; $j++)
        {
            $dp[$i][$j] = 0;
        }
    }

    // for each character of S
    for ($i = 1; $i <= $n1; $i++) 
    {

        // for each character in T
        for ($j = 1; $j <= $n2; $j++)
        {

            // if character are same in both 
            // the string
            if ($s[$i - 1] == $t[$j - 1]) 
                $dp[$i][$j] = 1 + $dp[$i][$j - 1] + 
                                  $dp[$i - 1][$j];     
            else
                $dp[$i][$j] = $dp[$i][$j - 1] + 
                              $dp[$i - 1][$j] - 
                              $dp[$i - 1][$j - 1];     
        }
    }

    return $dp[$n1][$n2];
}

// Driver Code
$s = "ajblqcpdz";
$t = "aefcnbtdi";

echo CommonSubsequencesCount($s, $t) ."\n";

// This code is contributed 
// by Akanksha Rai
?>
Python3
# Python3 program to count common
# subsequence in two strings

# return the number of common subsequence 
# in two strings
def CommonSubsequencesCount(s, t):

    n1 = len(s)
    n2 = len(t)
    dp = [[0 for i in range(n2 + 1)] 
             for i in range(n1 + 1)]

    # for each character of S
    for i in range(1, n1 + 1):

        # for each character in T
        for j in range(1, n2 + 1):

            # if character are same in both 
            # the string
            if (s[i - 1] == t[j - 1]):
                dp[i][j] = (1 + dp[i][j - 1] + 
                                dp[i - 1][j])         
            else:
                dp[i][j] = (dp[i][j - 1] + dp[i - 1][j] -
                            dp[i - 1][j - 1])         
        
    return dp[n1][n2]

# Driver Code
s = "ajblqcpdz"
t = "aefcnbtdi"

print(CommonSubsequencesCount(s, t))

# This code is contributed by Mohit Kumar

Output
11

Complexity Analysis:

  • Time Complexity : O(n1 * n2) 
  • Auxiliary Space : O(n1 * n2)


Efficient approach : Space optimization

In previous approach the current value dp[i][j] is only depend upon the current and previous row values of DP. So to optimize the space complexity we use a single 1D array to store the computations.

Implementation steps:

  • Create a 1D vector prev of size n2+1 and initialize it with 0.
  • Set a base case by initializing the values of prev.
  • Now iterate over subproblems by the help of nested loop and get the current value from previous computations.
  • Now Create a temporary 1d vector curr used to store the current values from previous computations.
  • After every iteration assign the value of curr to prev for further iteration.
  • At last return and print the final answer stored in prev[n2]

Implementation: 
 

C++
// C++ program to count common subsequence in two strings
#include <bits/stdc++.h>
using namespace std;

// return the number of common subsequence in
// two strings
int CommonSubsequencesCount(string s, string t)
{
    int n1 = s.length();
    int n2 = t.length();
    

    // to store previous computaions of subproblems
    vector<int>prev(n2+1 , 0);


    // for each character of S
    for (int i = 1; i <= n1; i++) {
        vector<int>curr(n2 +1 , 0);
        // for each character in T
        for (int j = 1; j <= n2; j++) {

            // if character are same in both
            // the string
            if (s[i - 1] == t[j - 1])
                curr[j] = 1 + curr[j - 1] + prev[j];        
            else
                curr[j] = curr[j - 1] + prev[j] - prev[j - 1];        
        }
            
        // assigning values 
        // for iterate further
        prev = curr;
    }
    
    // return final answer
    return prev[n2];
}

// Driver Program
int main()
{
    string s = "ajblqcpdz";
    string t = "aefcnbtdi";

    cout << CommonSubsequencesCount(s, t) << endl;
    return 0;
}
Java
import java.util.*;

public class Main {

    // Function to count the number of common subsequences in two strings
    public static int CommonSubsequencesCount(String s, String t) {
        int n1 = s.length();
        int n2 = t.length();

        // To store previous computations of subproblems
        int[] prev = new int[n2 + 1];

        // For each character of S
        for (int i = 1; i <= n1; i++) {
            int[] curr = new int[n2 + 1];

            // For each character in T
            for (int j = 1; j <= n2; j++) {
                // If characters are same in both the strings
                if (s.charAt(i - 1) == t.charAt(j - 1)) {
                    curr[j] = 1 + curr[j - 1] + prev[j];
                } else {
                    curr[j] = curr[j - 1] + prev[j] - prev[j - 1];
                }
            }

            // Assigning values for further iterations
            prev = curr;
        }

        // Return the final answer
        return prev[n2];
    }

    // Driver program
    public static void main(String[] args) {
        String s = "ajblqcpdz";
        String t = "aefcnbtdi";

        System.out.println(CommonSubsequencesCount(s, t));
    }
}
C#
using System;

public class CommonSubsequenceCount {
    // return the number of common subsequence in
    // two strings
    public static int Count(string s, string t)
    {
        int n1 = s.Length;
        int n2 = t.Length;

        // to store previous computations of subproblems
        int[] prev = new int[n2 + 1];

        // for each character of S
        for (int i = 1; i <= n1; i++) {
            int[] curr = new int[n2 + 1];

            // for each character in T
            for (int j = 1; j <= n2; j++) {
                // if characters are the same in both
                // strings
                if (s[i - 1] == t[j - 1])
                    curr[j] = 1 + curr[j - 1] + prev[j];
                else
                    curr[j] = curr[j - 1] + prev[j]
                              - prev[j - 1];
            }

            // assign values for further iteration
            prev = curr;
        }

        // return final answer
        return prev[n2];
    }

    public static void Main()
    {
        string s = "ajblqcpdz";
        string t = "aefcnbtdi";

        Console.WriteLine(Count(s, t));
    }
}
JavaScript
// Javascript program to count common subsequence in two strings

// return the number of common subsequence in
// two strings
function CommonSubsequencesCount(s, t) {
    let n1 = s.length;
    let n2 = t.length;
    
    // to store previous computaions of subproblems
    let prev = new Array(n2+1).fill(0);
    
    // for each character of s
    for (let i = 1; i <= n1; i++) {
        let curr = new Array(n2 + 1).fill(0);
        // for each character in t
        for (let j = 1; j <= n2; j++) {
            // if character are same in both
            // the string
            if (s[i - 1] === t[j - 1])
                curr[j] = 1 + curr[j - 1] + prev[j];        
            else
                curr[j] = curr[j - 1] + prev[j] - prev[j - 1];        
        }
        // assigning values 
        // for iterate further
        prev = curr;
    }
    // return final answer
    return prev[n2];
}

// Driver Program
let s = "ajblqcpdz";
let t = "aefcnbtdi";
console.log(CommonSubsequencesCount(s, t));
Python3
def CommonSubsequencesCount(s, t):
    n1 = len(s)
    n2 = len(t)

    # to store previous computations of subproblems
    prev = [0] * (n2 + 1)

    # for each character of S
    for i in range(1, n1 + 1):
        curr = [0] * (n2 + 1)
        # for each character in T
        for j in range(1, n2 + 1):
            # if characters are the same in both strings
            if s[i - 1] == t[j - 1]:
                curr[j] = 1 + curr[j - 1] + prev[j]
            else:
                curr[j] = curr[j - 1] + prev[j] - prev[j - 1]
        # assigning values for iteration
        prev = curr
    
    # return the final answer
    return prev[n2]

# Driver Program
if __name__ == "__main__":
    s = "ajblqcpdz"
    t = "aefcnbtdi"
    print(CommonSubsequencesCount(s, t))

Output
11

Time Complexity : O(n1 * n2) 
Auxiliary Space : O(n2)


Next Article

Similar Reads