Find the equal pairs of subsequence of S and subsequence of T

Given two arrays S[] and T[] of size N and M respectively. The task is to find the pairs of subsequences of S[] and subsequences of T[] which are the same in content. Answer could be very large. So, print the answer modulo 109 + 7.

Examples:

Input: S[] = {1, 1}, T[] = {1, 1}
Output: 6
Subsequences of S[] are {}, {1}, {1} and {1, 1}.
Subsequences of T[] are {}, {1}, {1} and {1, 1}.
All the valid pairs are ({}, {}), ({1}, {1}), ({1}, {1}),
({1}, {1}), ({1}, {1}) and ({1, 1}, {1, 1}).

Input: S[] = {1, 3}, T[] = {3, 1}
Output: 3

Approach: Let dp[i][j] be the number of ways to create subsequences only using the first i elements of S[] and the first j elements of T[] such that the subsequences are the same and the ith element of S[] and the jth element of T[] are part of the subsequences.
Basically, dp[i][j] is the answer to the problem if only the first i elements of S[] and the first j elements of T[] are considered. If S[i] != T[j] then dp[i][j] = 0 because no subsequence will end by using the ith element of S[] and the jth element of T[]. If S[i] = T[j] then dp[i][j] = ∑k=1i-1l=1j-1 dp[k][l] + 1 because the previous index of S[] can be any index ≤ i and the previous index of T[] can be any index ≤ j.
As a base case, dp[0][0] = 1. This represents the case where no element is taken. The runtime of this is O(N2 * M2) but we can speed this up by precomputing the sums.
Let sum[i][j] = ∑k=1il=1jdp[k][l] which is a 2D prefix sum of the dp array. sum[i][j] = sum[i – 1][j] + sum[i][j – 1] – sum[i – 1][j – 1] + dp[i][j]. With sum[i][j], each state dp[i][j] can now be calculated in O(1).
Since there are N * M states, the runtime will be O(N * M).



Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
  
#define mod (int)(1e9 + 7)
  
// Function to return the pairs of subsequences
// from S[] and subsequences from T[] such
// that both have the same content
int subsequence(int S[], int T[], int n, int m)
{
  
    // Create dp array
    int dp[n + 1][m + 1];
  
    // Base values
    for (int i = 0; i <= n; i++)
        dp[i][0] = 1;
  
    // Base values
    for (int j = 0; j <= m; j++)
        dp[0][j] = 1;
  
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
  
            // Keep previous dp value
            dp[i][j] = dp[i - 1][j]
                       + dp[i][j - 1]
                       - dp[i - 1][j - 1];
  
            // If both elements are same
            if (S[i - 1] == T[j - 1])
                dp[i][j] += dp[i - 1][j - 1];
  
            dp[i][j] += mod;
            dp[i][j] %= mod;
        }
    }
  
    // Return the required answer
    return dp[n][m];
}
  
// Driver code
int main()
{
    int S[] = { 1, 1 };
    int n = sizeof(S) / sizeof(S[0]);
  
    int T[] = { 1, 1 };
    int m = sizeof(T) / sizeof(T[0]);
  
    cout << subsequence(S, T, n, m);
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation of the approach 
import java.util.*; 
  
class GFG 
  
// Function to return the pairs of subsequences 
// from S[] and subsequences from T[] such 
// that both have the same content 
static int subsequence(int[] S, int[] T, 
                       int n, int m) 
  
    // Create dp array 
    int [][] dp = new int[n + 1][m + 1];
    int mod = 1000000007;
  
    // Base values 
    for (int i = 0; i <= n; i++) 
        dp[i][0] = 1
  
    // Base values 
    for (int j = 0; j <= m; j++) 
        dp[0][j] = 1
  
    for (int i = 1; i <= n; ++i) 
    
        for (int j = 1; j <= m; ++j)
        
  
            // Keep previous dp value 
            dp[i][j] = dp[i - 1][j] + 
                       dp[i][j - 1] - 
                       dp[i - 1][j - 1]; 
  
            // If both elements are same 
            if (S[i - 1] == T[j - 1]) 
                dp[i][j] += dp[i - 1][j - 1]; 
  
            dp[i][j] += mod; 
            dp[i][j] %= mod; 
        
    
  
    // Return the required answer 
    return dp[n][m]; 
  
  
// Driver code 
public static void main(String []args) 
    int S[] = { 1, 1 }; 
    int n = S.length;
  
    int T[] = { 1, 1 }; 
    int m = T.length; 
  
    System.out.println(subsequence(S, T, n, m)); 
  
// This code is contributed by Sanjit Prasad

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 implementation of the approach 
import numpy as np
  
mod = int(1e9 + 7
  
# Function to return the pairs of subsequences 
# from S[] and subsequences from T[] such 
# that both have the same content 
def subsequence(S, T, n, m) : 
  
    # Create dp array 
    dp = np.zeros((n + 1, m + 1)); 
  
    # Base values 
    for i in range(n + 1) :
        dp[i][0] = 1
  
    # Base values 
    for j in range(m + 1) : 
        dp[0][j] = 1
  
    for i in range(1, n + 1) :
        for j in range(1, m + 1) :
  
            # Keep previous dp value 
            dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - \
                       dp[i - 1][j - 1]; 
  
            # If both elements are same 
            if (S[i - 1] == T[j - 1]) :
                dp[i][j] += dp[i - 1][j - 1]; 
  
            dp[i][j] += mod; 
            dp[i][j] %= mod; 
  
    # Return the required answer 
    return dp[n][m]; 
  
# Driver code 
if __name__ == "__main__"
  
    S = [ 1, 1 ]; 
    n = len(S); 
  
    T = [ 1, 1 ]; 
    m = len(T); 
  
    print(subsequence(S, T, n, m)); 
  
# This code is contributed by kanugargng

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# implementation of the approach 
using System;
  
class GFG 
  
    // Function to return the pairs of subsequences 
    // from S[] and subsequences from T[] such 
    // that both have the same content 
    static int subsequence(int[] S, int[] T, 
                           int n, int m) 
    
      
        // Create dp array 
        int [,] dp = new int[n + 1, m + 1]; 
        int mod = 1000000007; 
      
        // Base values 
        for (int i = 0; i <= n; i++) 
            dp[i, 0] = 1; 
      
        // Base values 
        for (int j = 0; j <= m; j++) 
            dp[0, j] = 1; 
      
        for (int i = 1; i <= n; ++i) 
        
            for (int j = 1; j <= m; ++j) 
            
      
                // Keep previous dp value 
                dp[i, j] = dp[i - 1, j] + 
                           dp[i, j - 1] - 
                           dp[i - 1, j - 1]; 
      
                // If both elements are same 
                if (S[i - 1] == T[j - 1]) 
                    dp[i, j] += dp[i - 1, j - 1]; 
      
                dp[i, j] += mod; 
                dp[i, j] %= mod; 
            
        
      
        // Return the required answer 
        return dp[n, m]; 
    
      
    // Driver code 
    public static void Main() 
    
        int []S = { 1, 1 }; 
        int n = S.Length; 
      
        int []T = { 1, 1 }; 
        int m = T.Length; 
      
        Console.WriteLine(subsequence(S, T, n, m)); 
    
  
// This code is contributed by AnkitRai01

chevron_right


Output:

6

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

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.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.