Count Occurrences as a Subsequence

Last Updated : 2 Jun, 2026

Given two strings s1 and s2, count the number of subsequences of string s1 equal to string s2. Return the total count modulo 1e9+7.

Examples: 

Input: s1 = "geeksforgeeks", s2 = "gks"
Output: 4
Explanation: We can pick characters from s1 as a subsequence from indices [0, 3, 4], [0, 3, 12], [0, 11, 12] and [8, 11, 12]. So total 4 subsequences of s1 that are equal to s2.

Input: s1 = "problemoftheday", s2 = "geek"
Output: 0
Explanation: No subsequence of string s1 is equal to string s2.

Try It Yourself
redirect icon

[Naive Approach] Using Recursion - O(2^n) Time O(n + m) Space

The idea is to recursively process the characters of s1. For each character, either skip it or include it if it matches the current character of s2. Count all possible ways that successfully match every character of s2.

C++
#include <iostream>
using namespace std;

static const int MOD = 1e9 + 7;

int solve(string &s1, string &s2, int i, int j)
{
    // All characters of s2 are matched
    if (j == s2.size())
    {
        return 1;
    }

    // s1 is exhausted before matching s2
    if (i == s1.size())
    {
        return 0;
    }

    // Ignore current character of s1
    long long ans = solve(s1, s2, i + 1, j);

    // If characters match, consider current character
    if (s1[i] == s2[j])
    {
        ans += solve(s1, s2, i + 1, j + 1);
    }

    return ans % MOD;
}

int countWays(string &s1, string &s2)
{
    return solve(s1, s2, 0, 0);
}

// Driver Code
int main()
{
    string s1 = "geeksforgeeks";
    string s2 = "gks";

    cout << countWays(s1, s2);

    return 0;
}
Java
import java.util.*;

public class GfG {
    static final int MOD = 1000000007;

    static int solve(String s1, String s2, int i, int j)
    {
        // All characters of s2 are matched
        if (j == s2.length()) {
            return 1;
        }

        // s1 is exhausted before matching s2
        if (i == s1.length()) {
            return 0;
        }

        // Ignore current character of s1
        long ans = solve(s1, s2, i + 1, j);

        // If characters match, consider current character
        if (s1.charAt(i) == s2.charAt(j)) {
            ans += solve(s1, s2, i + 1, j + 1);
        }

        return (int)(ans % MOD);
    }

    static int countWays(String s1, String s2)
    {
        return solve(s1, s2, 0, 0);
    }

    // Driver Code
    public static void main(String[] args)
    {
        String s1 = "geeksforgeeks";
        String s2 = "gks";

        System.out.println(countWays(s1, s2));
    }
}
Python
MOD = 10**9 + 7


def solve(s1, s2, i, j):
    # All characters of s2 are matched
    if j == len(s2):
        return 1

    # s1 is exhausted before matching s2
    if i == len(s1):
        return 0

    # Ignore current character of s1
    ans = solve(s1, s2, i + 1, j)

    # If characters match, consider current character
    if s1[i] == s2[j]:
        ans += solve(s1, s2, i + 1, j + 1)

    return ans % MOD


def countWays(s1, s2):
    return solve(s1, s2, 0, 0)


# Driver Code
# Driver Code
if __name__ == "__main__":
    s1 = "geeksforgeeks"
    s2 = "gks"
    print(countWays(s1, s2))
C#
using System;

public class GfG {
    static readonly int MOD = 1000000007;

    static int Solve(string s1, string s2, int i, int j)
    {
        if (j == s2.Length)
            return 1;

        if (i == s1.Length)
            return 0;

        long ans = Solve(s1, s2, i + 1, j);

        if (s1[i] == s2[j])
            ans += Solve(s1, s2, i + 1, j + 1);

        return (int)(ans % MOD);
    }

    public static void Main()
    {
        string s1 = "geeksforgeeks";
        string s2 = "gks";

        Console.WriteLine(Solve(s1, s2, 0, 0));
    }
}
JavaScript
function solve(s1, s2, i, j)
{
    if (j === s2.length)
        return 1;
    if (i === s1.length)
        return 0;

    let ans = solve(s1, s2, i + 1, j);

    if (s1[i] === s2[j]) {
        ans += solve(s1, s2, i + 1, j + 1);
    }

    return ans;
}

function countWays(s1, s2)
{
    const MOD = 1000000007;
    return solve(s1, s2, 0, 0) % MOD;
}

// Driver Code
let s1 = "geeksforgeeks";
let s2 = "gks";

console.log(countWays(s1, s2));

Output
4

Time Complexity: O(2^n)
Auxiliary Space: O(n + m)

[Expected Approach - 1] Using Bottom-Up Dynamic Programming - (n * m) Time O(n * m) Space

The idea is to use Dynamic Programming where dp[i][j] stores the number of ways to form the first j characters of s2 using the first i characters of s1. For each character of s1:

  • If it matches the current character of s2, either include it in the subsequence or skip it.
  • Otherwise, skip the current character of s1.

The final answer is stored in dp[n][m].

Working of the Approach:

  • Create a DP table dp where dp[i][j] stores the number of ways to form the first j characters of s2 using the first i characters of s1.
  • Initialize dp[i][0] = 1 since an empty string can always be formed.
  • Initialize dp[0][j] = 0 for j > 0 since a non-empty string cannot be formed from an empty string.
  • If the current characters match, add the ways obtained by including and excluding the current character.
  • If the characters do not match, carry forward the count by skipping the current character of s1.
  • After filling the table, dp[n][m] gives the number of times s2 occurs as a subsequence in s1.
C++
#include <iostream>
#include <vector>
using namespace std;

int countWays(string &s1, string &s2)
{
    int n = s1.length(), m = s2.length();

    // create a table to store result for sub-problems
    vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));

    for (int i = 0; i <= m; i++)
        dp[0][i] = 0;
    for (int i = 0; i <= n; i++)
        dp[i][0] = 1;

    int mod = 1e9 + 7;

    // fill the table in bottom-up manner
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {

            // if last characters are same, we have two
            // options -
            // 1. consider last characters of both strings
            //    in solution
            // 2. ignore last character of first string
            if (s1[i - 1] == s2[j - 1])
            {
                dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j]) % mod;
            }

            // If last character are different, ignore
            // last character of first string
            else
            {
                dp[i][j] = dp[i - 1][j] % mod;
            }
        }
    }
    return dp[n][m] % mod;
}

// Driver Code
int main()
{
    string s1 = "geeksforgeeks";
    string s2 = "gks";

    cout << countWays(s1, s2);

    return 0;
}
C
#include <stdio.h>
#include <string.h>

#define mod 1000000007

int countWays(char *s1, char *s2)
{
    int n = strlen(s1), m = strlen(s2);

    // create a table to store result for sub-problems
    int dp[n + 1][m + 1];

    for (int i = 0; i <= m; i++)
        dp[0][i] = 0;
    for (int i = 0; i <= n; i++)
        dp[i][0] = 1;

    // fill the table in bottom-up manner
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            // if last characters are same, we have two
            // options -
            // 1. consider last characters of both strings
            //    in solution
            // 2. ignore last character of first string
            if (s1[i - 1] == s2[j - 1])
            {
                dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j]) % mod;
            }
            // If last character are different, ignore
            // last character of first string
            else
            {
                dp[i][j] = dp[i - 1][j] % mod;
            }
        }
    }
    return dp[n][m] % mod;
}

// Driver Code
int main()
{
    char s1[] = "geeksforgeeks";
    char s2[] = "gks";

    printf("%d", countWays(s1, s2));

    return 0;
}
Java
public class GfG {
    static int countWays(String s1, String s2)
    {
        int n = s1.length(), m = s2.length();

        // create a table to store result for sub-problems
        int[][] dp = new int[n + 1][m + 1];

        for (int i = 0; i <= m; i++)
            dp[0][i] = 0;
        for (int i = 0; i <= n; i++)
            dp[i][0] = 1;

        int mod = 1000000007;

        // fill the table in bottom-up manner
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {

                // if last characters are same, we have two
                // options -
                // 1. consider last characters of both
                // strings
                //    in solution
                // 2. ignore last character of first string
                if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
                    dp[i][j]
                        = (dp[i - 1][j - 1] + dp[i - 1][j])
                          % mod;
                }

                // If last character are different, ignore
                // last character of first string
                else {
                    dp[i][j] = dp[i - 1][j] % mod;
                }
            }
        }
        return dp[n][m] % mod;
    }

    public static void main(String[] args)
    {
        String s1 = "geeksforgeeks";
        String s2 = "gks";

        System.out.println(countWays(s1, s2));
    }
}
Python
def countWays(s1, s2):
    n = len(s1)
    m = len(s2)

    # create a table to store result for sub-problems
    dp = [[0] * (m + 1) for _ in range(n + 1)]

    for i in range(m + 1):
        dp[0][i] = 0
    for i in range(n + 1):
        dp[i][0] = 1

    mod = 10**9 + 7

    # fill the table in bottom-up manner
    for i in range(1, n + 1):
        for j in range(1, m + 1):

            # if last characters are same, we have two
            # options -
            # 1. consider last characters of both strings
            #    in solution
            # 2. ignore last character of first string
            if s1[i - 1] == s2[j - 1]:
                dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j]) % mod
            # If last character are different, ignore
            # last character of first string
            else:
                dp[i][j] = dp[i - 1][j] % mod
    return dp[n][m] % mod


# Driver Code
if __name__ == "__main__":
    s1 = "geeksforgeeks"
    s2 = "gks"
    print(countWays(s1, s2))
C#
using System;

public class GfG {
    public static int CountWays(string s1, string s2)
    {
        int n = s1.Length, m = s2.Length;

        // create a table to store result for sub-problems
        int[, ] dp = new int[n + 1, m + 1];

        for (int i = 0; i <= m; i++)
            dp[0, i] = 0;
        for (int i = 0; i <= n; i++)
            dp[i, 0] = 1;

        int mod = 1000000007;

        // fill the table in bottom-up manner
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                // if last characters are same, we have two
                // options -
                // 1. consider last characters of both
                // strings
                //    in solution
                // 2. ignore last character of first string
                if (s1[i - 1] == s2[j - 1]) {
                    dp[i, j]
                        = (dp[i - 1, j - 1] + dp[i - 1, j])
                          % mod;
                }
                // If last character are different, ignore
                // last character of first string
                else {
                    dp[i, j] = dp[i - 1, j] % mod;
                }
            }
        }
        return dp[n, m] % mod;
    }

    public static void Main()
    {
        string s1 = "geeksforgeeks";
        string s2 = "gks";

        Console.WriteLine(CountWays(s1, s2));
    }
}
JavaScript
function countWays(s1, s2)
{
    let n = s1.length, m = s2.length;

    // create a table to store result for sub-problems
    let dp = Array.from({length : n + 1},
                        () => Array(m + 1).fill(0));

    for (let i = 0; i <= m; i++)
        dp[0][i] = 0;
    for (let i = 0; i <= n; i++)
        dp[i][0] = 1;

    let mod = 1000000007;

    // fill the table in bottom-up manner
    for (let i = 1; i <= n; i++) {
        for (let j = 1; j <= m; j++) {

            // if last characters are same, we have two
            // options -
            // 1. consider last characters of both strings
            //    in solution
            // 2. ignore last character of first string
            if (s1[i - 1] == s2[j - 1]) {
                dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j])
                           % mod;
            }
            // If last character are different, ignore
            // last character of first string
            else {
                dp[i][j] = dp[i - 1][j] % mod;
            }
        }
    }
    return dp[n][m] % mod;
}

// Driver Code
let s1 = "geeksforgeeks";
let s2 = "gks";

console.log(countWays(s1, s2));

Output
4

Time Complexity: O(n * m)
Auxiliary Space: O(n * m)

[Expected Approach - 2] Using Dynamic Programming (Space Optimized) - O(n * m) Time and O(m) Space

The idea is to optimize the DP solution by using a single array instead of a 2D table. Here, dp[j] stores the number of ways to form the first j characters of s2. For each character of s1, we traverse s2 from right to left so that previous states are not overwritten. If the characters match, we either include the current character in the subsequence or skip it. This reduces the space requirement while maintaining the same time complexity.

Working of the Approach:

  • Use a 1D DP array dp where dp[j] stores the number of ways to form the first j characters of s2.
  • Initialize dp[0] = 1 since an empty string can always be formed.
  • Traverse each character of s1 one by one.
  • For every character of s1, traverse s2 from right to left to avoid overwriting values needed for future computations.
  • If the current characters match, update dp[j] by adding the ways of forming the previous prefix, i.e., dp[j - 1].
  • After processing all characters, dp[m] gives the number of times s2 occurs as a subsequence in s1.
C++
#include <iostream>
#include <vector>
using namespace std;

int countWays(string &s1, string &s2)
{
    int n = s1.length();
    int m = s2.length();

    int mod = 1e9 + 7;

    // dp[j] stores the number of ways to form
    // first j characters of s2
    vector<int> dp(m + 1, 0);

    // Empty string can always be formed
    dp[0] = 1;

    for (int i = 1; i <= n; i++)
    {

        // Traverse from right to left
        for (int j = m; j >= 1; j--)
        {

            // If current characters match,
            // include or exclude current character
            if (s1[i - 1] == s2[j - 1])
            {
                dp[j] = (dp[j] + dp[j - 1]) % mod;
            }
        }
    }

    return dp[m];
}

// Driver Code
int main()
{
    string s1 = "geeksforgeeks";
    string s2 = "gks";

    cout << countWays(s1, s2);

    return 0;
}
C
#include <stdio.h>
#include <string.h>

#define MOD 1000000007

int countWays(char *s1, char *s2)
{
    int n = strlen(s1);
    int m = strlen(s2);

    int dp[m + 1];

    // manual initialization
    for (int j = 0; j <= m; j++)
        dp[j] = 0;

    dp[0] = 1;

    for (int i = 1; i <= n; i++)
    {
        for (int j = m; j >= 1; j--)
        {
            if (s1[i - 1] == s2[j - 1])
            {
                dp[j] = (dp[j] + dp[j - 1]) % MOD;
            }
        }
    }

    return dp[m];
}

// Driver Code
int main()
{
    char s1[] = "geeksforgeeks";
    char s2[] = "gks";

    printf("%d", countWays(s1, s2));

    return 0;
}
Java
import java.util.*;

public class GfG {
    static int countWays(String s1, String s2)
    {
        int n = s1.length();
        int m = s2.length();

        int mod = 1000000007;

        // dp[j] stores the number of ways to form
        // first j characters of s2
        int[] dp = new int[m + 1];

        // Empty string can always be formed
        dp[0] = 1;

        for (int i = 1; i <= n; i++) {

            // Traverse from right to left
            for (int j = m; j >= 1; j--) {

                // If current characters match,
                // include or exclude current character
                if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
                    dp[j] = (dp[j] + dp[j - 1]) % mod;
                }
            }
        }

        return dp[m];
    }

    // Driver Code
    public static void main(String[] args)
    {
        String s1 = "geeksforgeeks";
        String s2 = "gks";

        System.out.println(countWays(s1, s2));
    }
}
Python
def countWays(s1, s2):
    n = len(s1)
    m = len(s2)

    mod = 10**9 + 7

    # dp[j] stores the number of ways to form
    # first j characters of s2
    dp = [0] * (m + 1)

    # Empty string can always be formed
    dp[0] = 1

    for i in range(1, n + 1):

        # Traverse from right to left
        for j in range(m, 0, -1):

            # If current characters match,
            # include or exclude current character
            if s1[i - 1] == s2[j - 1]:
                dp[j] = (dp[j] + dp[j - 1]) % mod

    return dp[m]


# Driver Code
if __name__ == "__main__":
    s1 = "geeksforgeeks"
    s2 = "gks"
    print(countWays(s1, s2))
C#
using System;

public class GfG {
    public static int countWays(string s1, string s2)
    {
        int n = s1.Length;
        int m = s2.Length;
        int mod = 1000000007;

        int[] dp = new int[m + 1];
        dp[0] = 1;

        for (int i = 1; i <= n; i++) {
            for (int j = m; j >= 1; j--) {
                if (s1[i - 1] == s2[j - 1]) {
                    dp[j] = (dp[j] + dp[j - 1]) % mod;
                }
            }
        }

        return dp[m];
    }

    public static void Main()
    {
        string s1 = "geeksforgeeks";
        string s2 = "gks";

        Console.WriteLine(countWays(s1, s2));
    }
}
JavaScript
function countWays(s1, s2) {
    let n = s1.length;
    let m = s2.length;

    let mod = 10**9 + 7;

    // dp[j] stores the number of ways to form
    // first j characters of s2
    let dp = new Array(m + 1).fill(0);

    // Empty string can always be formed
    dp[0] = 1;

    for (let i = 1; i <= n; i++) {

        // Traverse from right to left
        for (let j = m; j >= 1; j--) {

            // If current characters match,
            // include or exclude current character
            if (s1[i - 1] === s2[j - 1]) {
                dp[j] = (dp[j] + dp[j - 1]) % mod;
            }
        }
    }

    return dp[m];
}

// Driver Code
let s1 = "geeksforgeeks";
let s2 = "gks";

console.log(countWays(s1, s2));

Output
4

Time Complexity: O(n * m)
Auxiliary Space: O(m)

Comment