Given a two strings S and T, find the count of distinct occurrences of T in S as a subsequence.
Examples:
Input: S = banana, T = ban
Output: 3
Explanation: T appears in S as below three subsequences.
[ban], [ba n], [b an]
Input: S = geeksforgeeks, T = ge
Output: 6
Explanation: T appears in S as below three subsequences.
[ge], [ ge], [g e], [g e] [g e]
and [ g e]
Approach: Create a recursive function such that it returns count of subsequences of S that match T. Here m is the length of T and n is length of S. This problem can be recursively defined as below.
- Given the string T is an empty string, returning 1 as an empty string can be the subsequence of all.
- Given the string S is an empty string, returning 0 as no string can be the subsequence of an empty string.
- If the last character of S and T do not match, then remove the last character of S and call the recursive function again. Because the last character of S cannot be a part of the subsequence or remove it and check for other characters.
- If the last character of S match then there can be two possibilities, first there can be a subsequence where the last character of S is a part of it and second where it is not a part of the subsequence. So the required value will be the sum of both. Call the recursive function once with last character of both the strings removed and again with only last character of S removed.

Blue round rectangles represent accepted states or there are a subsequence and red round rectangles represent No subsequence can be formed.
Implementation of Recursive Approach:
C++
#include <bits/stdc++.h>
using namespace std;
int f(int i, int j, string s, string t)
{
if (j >= t.size()) {
return 1;
}
if (i >= s.size()) {
return 0;
}
if (s[i] == t[j]) {
return f(i + 1, j + 1, s, t) + f(i + 1, j, s, t);
}
return f(i + 1, j, s, t);
}
int findSubsequenceCount(string s, string t)
{
return f(0, 0, s, t);
}
int main()
{
string T = "ge";
string S = "geeksforgeeks";
cout << findSubsequenceCount(S, T) << endl;
return 0;
}
|
Java
import java.io.*;
class GFG {
static int f(int i, int j, String s,
String t)
{
if (j >= t.length()) {
return 1;
}
if (i >= s.length()) {
return 0;
}
if (s.charAt(i) == t.charAt(j)) {
return f(i + 1, j + 1, s, t)
+ f(i + 1, j, s, t);
}
return f(i + 1, j, s, t);
}
public static void main(String[] args)
{
String T = "ge";
String S = "geeksforgeeks";
System.out.println(
f(0, 0, S, T));
}
}
|
Python3
def f(i, j, s, t):
if(j >= len(t)):
return 1
if(i >= len(s)):
return 0
if(s[i] == t[j]):
return f(i + 1, j + 1, s, t) + f(i + 1, j, s, t)
return f(i + 1, j, s, t)
def findSubsequenceCount(s, t):
return f(0, 0, s, t)
T = "ge"
S = "geeksforgeeks"
print(findSubsequenceCount(S,T))
|
C#
using System;
class GFG {
static int f(int i, int j, string s, string t)
{
if (j >= t.Length) {
return 1;
}
if (i >= s.Length) {
return 0;
}
if (s[i] == t[j])
return f(i + 1, j + 1, s, t) + f(i + 1, j, s, t);
return f(i + 1, j, s, t);
}
static int findSubsequenceCount(string s, string t)
{
return f(0, 0, s, t);
}
public static void Main()
{
string T = "ge";
string S = "geeksforgeeks";
Console.WriteLine(findSubsequenceCount(S, T));
}
}
|
Javascript
<script>
function f(i, j, s, t) {
if (j >= t.length) {
return 1;
}
if (i >= s.length) {
return 0;
}
if (s[i] == t[j]) {
return f(i + 1, j + 1, s, t) + f(i + 1, j, s, t);
}
return f(i + 1, j, s, t);
}
function findSubsequenceCount(s, t) {
return f(0, 0, s, t);
}
let T = "ge";
let S = "geeksforgeeks";
document.write(findSubsequenceCount(S, T))
</script>
|
Since there are overlapping subproblems in the above recurrence result, Dynamic Programming approach can be applied to solve the above problem. Store the subproblems in a Hashmap or an array and return the value when the function is called again.
Algorithm:
- Create a 2D array mat[m+1][n+1] where m is length of string T and n is length of string S. mat[i][j] denotes the number of distinct subsequence of substring S(1..i) and substring T(1..j) so mat[m][n] contains our solution.
- Initialize the first column with all 0s. An empty string can’t have another string as subsequence
- Initialize the first row with all 1s. An empty string is a subsequence of all.
- Fill the matrix in bottom-up manner, i.e. all the sub problems of the current string is calculated first.
- Traverse the string T from start to end. (counter is i)
- For every iteration of the outer loop, Traverse the string S from start to end. (counter is j)
- If the character at ith index of string T matches with jth character of string S, the value is obtained considering two cases. First, is all the substrings without last character in S and second is the substrings without last characters in both, i.e mat[i+1][j] + mat[i][j] .
- Else the value will be same even if jth character of S is removed, i.e. mat[i+1][j]
- Print the value of mat[m-1][n-1] as the answer.
C++
#include <bits/stdc++.h>
using namespace std;
int findSubsequenceCount(string S, string T)
{
int m = T.length(), n = S.length();
if (m > n)
return 0;
int mat[m + 1][n + 1];
for (int i = 1; i <= m; i++)
mat[i][0] = 0;
for (int j = 0; j <= n; j++)
mat[0][j] = 1;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (T[i - 1] != S[j - 1])
mat[i][j] = mat[i][j - 1];
else
mat[i][j] = mat[i][j - 1] + mat[i - 1][j - 1];
}
}
return mat[m][n];
}
int main()
{
string T = "ge";
string S = "geeksforgeeks";
cout << findSubsequenceCount(S, T) << endl;
return 0;
}
|
Java
import java.io.*;
class GFG {
static int findSubsequenceCount(String S, String T)
{
int m = T.length();
int n = S.length();
if (m > n)
return 0;
int mat[][] = new int[m + 1][n + 1];
for (int i = 1; i <= m; i++)
mat[i][0] = 0;
for (int j = 0; j <= n; j++)
mat[0][j] = 1;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (T.charAt(i - 1) != S.charAt(j - 1))
mat[i][j] = mat[i][j - 1];
else
mat[i][j] = mat[i][j - 1] + mat[i - 1][j - 1];
}
}
return mat[m][n];
}
public static void main(String[] args)
{
String T = "ge";
String S = "geeksforgeeks";
System.out.println(findSubsequenceCount(S, T));
}
}
|
Python3
def findSubsequenceCount(S, T):
m = len(T)
n = len(S)
if m > n:
return 0
mat = [[0 for _ in range(n + 1)]
for __ in range(m + 1)]
for i in range(1, m + 1):
mat[i][0] = 0
for j in range(n + 1):
mat[0][j] = 1
for i in range(1, m + 1):
for j in range(1, n + 1):
if T[i - 1] != S[j - 1]:
mat[i][j] = mat[i][j - 1]
else:
mat[i][j] = (mat[i][j - 1] +
mat[i - 1][j - 1])
return mat[m][n]
if __name__ == "__main__":
T = "ge"
S = "geeksforgeeks"
print(findSubsequenceCount(S, T))
|
C#
using System;
class GFG {
static int findSubsequenceCount(string S, string T)
{
int m = T.Length;
int n = S.Length;
if (m > n)
return 0;
int[, ] mat = new int[m + 1, n + 1];
for (int i = 1; i <= m; i++)
mat[i, 0] = 0;
for (int j = 0; j <= n; j++)
mat[0, j] = 1;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (T[i - 1] != S[j - 1])
mat[i, j] = mat[i, j - 1];
else
mat[i, j] = mat[i, j - 1] + mat[i - 1, j - 1];
}
}
return mat[m, n];
}
public static void Main()
{
string T = "ge";
string S = "geeksforgeeks";
Console.WriteLine(findSubsequenceCount(S, T));
}
}
|
PHP
<?php
function findSubsequenceCount($S, $T)
{
$m = strlen($T); $n = strlen($S);
if ($m > $n)
return 0;
$mat = array(array());
for ($i = 1; $i <= $m; $i++)
$mat[$i][0] = 0;
for ($j = 0; $j <= $n; $j++)
$mat[0][$j] = 1;
for ($i = 1; $i <= $m; $i++)
{
for ($j = 1; $j <= $n; $j++)
{
if ($T[$i - 1] != $S[$j - 1])
$mat[$i][$j] = $mat[$i][$j - 1];
else
$mat[$i][$j] = $mat[$i][$j - 1] +
$mat[$i - 1][$j - 1];
}
}
return $mat[$m][$n];
}
$T = "ge";
$S = "geeksforgeeks";
echo findSubsequenceCount($S, $T) . "\n";
|
Javascript
<script>
function findSubsequenceCount(S, T)
{
let m = T.length;
let n = S.length;
if (m > n)
return 0;
let mat = new Array(m + 1);
for (let i = 0; i <= m; i++)
{
mat[i] = new Array(n + 1);
for (let j = 0; j <= n; j++)
{
mat[i][j] = 0;
}
}
for (let i = 1; i <= m; i++)
mat[i][0] = 0;
for (let j = 0; j <= n; j++)
mat[0][j] = 1;
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
if (T[i - 1] != S[j - 1])
mat[i][j] = mat[i][j - 1];
else
mat[i][j] = mat[i][j - 1] +
mat[i - 1][j - 1];
}
}
return mat[m][n];
}
let T = "ge";
let S = "geeksforgeeks";
document.write(findSubsequenceCount(S, T));
</script>
|
Complexity Analysis:
- Time Complexity: O(m*n).
Only one traversal of the matrix is needed, so the time Complexity is O(m*n) - Auxiliary Space: O(m*n).
A matrix of size m*n is needed so the space complexity is O(m*n).
Note:Since mat[i][j] accesses elements of the current row and previous row only, we can optimize auxiliary space just by using two rows only reducing space from m*n to 2*n.
Another way to solve dynamic programming is by Top-Down approach is by memoization
Below is the code:
C++
#include <bits/stdc++.h>
using namespace std;
int f(int i, int j, string s, string t,
vector<vector<int> >& dp)
{
if (t.size() - j > s.size() - i)
return 0;
if (j == t.size()) {
return 1;
}
if (i == s.size()) {
return 0;
}
if (dp[i][j] != -1) {
return dp[i][j];
}
if (s[i] == t[j]) {
return dp[i][j] = f(i + 1, j + 1, s, t, dp)
+ f(i + 1, j, s, t, dp);
}
return dp[i][j] = f(i + 1, j, s, t, dp);
}
int findSubsequenceCount(string s, string t)
{
vector<vector<int> > dp(s.size(),
vector<int>(t.size(), -1));
return f(0, 0, s, t, dp);
}
int main()
{
string T = "ge";
string S = "geeksforgeeks";
cout << findSubsequenceCount(S, T) << endl;
return 0;
}
|
Java
import java.util.*;
class Program
{
static int f(int i, int j, String s, String t,
int dp[][])
{
if (t.length() - j > s.length() - i)
return 0;
if (j == t.length()) {
return 1;
}
if (i == s.length()) {
return 0;
}
if (dp[i][j] != -1) {
return dp[i][j];
}
if (s.charAt(i) == t.charAt(j)) {
return dp[i][j] = f(i + 1, j + 1, s, t, dp)
+ f(i + 1, j, s, t, dp);
}
return dp[i][j] = f(i + 1, j, s, t, dp);
}
static int findSubsequenceCount(String s, String t)
{
int dp[][] = new int[s.length() + 1][t.length() + 1];
for (int i = 0; i < s.length() + 1; i++)
Arrays.fill(dp[i], -1);
return f(0, 0, s, t, dp);
}
public static void main(String[] args)
{
String T = "ge";
String S = "geeksforgeeks";
System.out.println(findSubsequenceCount(S, T));
}
}
|
Python3
def f(i, j, s, t, dp):
if len(t) - j > len(s) - i:
return 0
if j == len(t):
return 1
if i == len(s):
return 0
if dp[i][j] != -1:
return dp[i][j]
if s[i] == t[j]:
count1 = f(i + 1, j + 1, s, t, dp)
count2 = f(i + 1, j, s, t, dp)
dp[i][j] = count1 + count2
return dp[i][j]
dp[i][j] = f(i + 1, j, s, t, dp)
return dp[i][j]
def findSubsequenceCount(s, t):
dp = [[-1 for j in range(len(t))] for i in range(len(s))]
return f(0, 0, s, t, dp)
if __name__ == '__main__':
T = "ge"
S = "geeksforgeeks"
print(findSubsequenceCount(S, T))
|
C#
using System;
public class Program
{
static int f(int i, int j, string s, string t,
int[,] dp)
{
if (t.Length - j > s.Length - i)
return 0;
if (j == t.Length)
{
return 1;
}
if (i == s.Length)
{
return 0;
}
if (dp[i, j] != -1)
{
return dp[i, j];
}
if (s[i] == t[j])
{
return dp[i, j] = f(i + 1, j + 1, s, t, dp)
+ f(i + 1, j, s, t, dp);
}
return dp[i, j] = f(i + 1, j, s, t, dp);
}
static int findSubsequenceCount(string s, string t)
{
int[,] dp = new int[s.Length + 1, t.Length + 1];
for (int i = 0; i < s.Length + 1; i++)
for (int j = 0; j < t.Length + 1; j++)
dp[i, j] = -1;
return f(0, 0, s, t, dp);
}
public static void Main(string[] args)
{
string T = "ge";
string S = "geeksforgeeks";
Console.WriteLine(findSubsequenceCount(S, T));
}
}
|
Javascript
function f(i, j, s, t, dp) {
if (t.length - j > s.length - i) {
return 0;
}
if (j === t.length) {
return 1;
}
if (i === s.length) {
return 0;
}
if (dp[i][j] !== -1) {
return dp[i][j];
}
if (s[i] === t[j]) {
dp[i][j] = f(i + 1, j + 1, s, t, dp) + f(i + 1, j, s, t, dp);
return dp[i][j];
}
return dp[i][j] = f(i + 1, j, s, t, dp);
}
function findSubsequenceCount(s, t) {
let dp = Array(s.length).fill().map(() => Array(t.length).fill(-1));
return f(0, 0, s, t, dp);
}
let T = "ge";
let S = "geeksforgeeks";
console.log(findSubsequenceCount(S, T));
|
Complexity Analysis:
- Time Complexity: O(m*n). Only one traversal of the matrix is needed, so the time Complexity is O(m*n)
- Auxiliary Space: O(m*n) ignoring recursion stack space
Trie Approach:
A Trie is a data structure that can be used to efficiently search for a subsequence in a larger sequence. You can build a Trie for the subsequence and then use it to traverse the original sequence to find all occurrences.
Algorithm:
- Build a Trie: Construct a Trie for the subsequence you want to find. Each node in the Trie represents a character in the subsequence, and each edge represents a transition from one character to the next.
- Traverse the original sequence: Traverse the original sequence character by character. At each step, look for the current character in the Trie. If the current character is not in the Trie, skip it and move to the next character. If the current character is in the Trie, follow the corresponding edge to the next node and continue the traversal.
- Count occurrences: When you reach the end of the Trie (i.e., you have traversed all the characters in the subsequence), increment a count variable to indicate that you have found an occurrence of the subsequence in the original sequence. Note that you should only count each occurrence once, even if it appears multiple times in the original sequence.
- Continue the traversal: After counting an occurrence, continue the traversal from the next character in the original sequence.
- Return the count: After traversing the entire original sequence, return the count variable, which represents the number of distinct occurrences of the subsequence in the original sequence.
One advantage of using a Trie for this problem is that it can be more efficient than some other methods, especially if the subsequence is long and the original sequence is large.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
const int ALPHABET_SIZE = 26;
struct TrieNode {
int count;
TrieNode* children[ALPHABET_SIZE];
TrieNode()
{
count = 0;
for (int i = 0; i < ALPHABET_SIZE; i++) {
children[i] = nullptr;
}
}
};
class Trie {
public:
Trie() { root = new TrieNode(); }
void insert(string word)
{
TrieNode* curr = root;
for (char c : word) {
int index = c - 'a';
if (!curr->children[index]) {
curr->children[index] = new TrieNode();
}
curr = curr->children[index];
}
curr->count++;
}
int countSubseq(string str)
{
int n = str.length();
vector<TrieNode*> dp(n + 1, nullptr);
dp[0] = root;
for (int i = 1; i <= n; i++) {
char c = str[i - 1];
int index = c - 'a';
dp[i] = root;
if (dp[i - 1]->children[index]) {
dp[i] = dp[i - 1]->children[index];
}
dp[i]->count++;
}
return root->count;
}
private:
TrieNode* root;
};
int main()
{
Trie trie;
string subseq = "ban";
trie.insert(subseq);
string str = "banana";
int count = trie.countSubseq(str);
cout << count << endl;
return 0;
}
|
Java
import java.util.*;
class TrieNode {
int count;
TrieNode[] children;
TrieNode()
{
count = 0;
children = new TrieNode[26];
}
}
class Trie {
private TrieNode root;
public Trie() { root = new TrieNode(); }
public void insert(String word)
{
TrieNode curr = root;
for (char c : word.toCharArray()) {
int index = c - 'a';
if (curr.children[index] == null) {
curr.children[index] = new TrieNode();
}
curr = curr.children[index];
}
curr.count++;
}
public int countSubseq(String str)
{
int n = str.length();
List<TrieNode> dp = new ArrayList<>();
for (int i = 0; i <= n; i++) {
dp.add(null);
}
dp.set(0, root);
for (int i = 1; i <= n; i++) {
char c = str.charAt(i - 1);
int index = c - 'a';
dp.set(i, root);
if (dp.get(i - 1).children[index] != null) {
dp.set(i, dp.get(i - 1).children[index]);
}
dp.get(i).count++;
}
return root.count;
}
}
class Main {
public static void main(String[] args)
{
Trie trie = new Trie();
String subseq = "ban";
trie.insert(subseq);
String str = "banana";
int count = trie.countSubseq(str);
System.out.println(count);
}
}
|
Time Complexity: O(N*M), where N is the length of the original sequence and M is the length of the subsequence.
Auxiliary Space: O(N*M)
This article is contributed by Utkarsh Trivedi. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Please Login to comment...