Print all subsequences of a string
Last Updated :
18 Oct, 2024
Given a string, we have to find out all its subsequences of it. A String is said to be a subsequence of another String, if it can be obtained by deleting 0 or more character without changing its order.
Examples:
Input : ab
Output : "", "a", "b", "ab"

Input : abc
Output : "", "a", "b", "c", "ab", "ac", "bc", "abc"
Pick and Don't Pick Recursive Approach
We begin with the last character and for every character, we make two choices, we either pick it or do not pick it and make two recursive calls. This way generate all possible subsequences.
C++
#include <bits/stdc++.h>
using namespace std;
// Find all subsequences recursively
void printSubRec(string s, string curr)
{
// Base Case : s is empty, print
// current subsequence
if (s.empty()) {
cout << curr << endl;
return;
}
// curr is passed with including
// the first character of the string
printSubRec(s.substr(1), curr + s[0]);
// curr is passed without including
// the first character of the string
printSubRec(s.substr(1), curr);
}
// Wrapper method for printSubRec
void printSubs(string s)
{
string curr = "";
printSubRec(s, curr);
}
// Driver code
int main()
{
string s = "ab";
printSubs(s);
return 0;
}
Java
// Java program for the above approach
import java.util.*;
class GFG {
// Declare a global list
static List<String> al = new ArrayList<>();
// Creating a public static Arraylist such that
// we can store values
// IF there is any question of returning the
// we can directly return too// public static
// ArrayList<String> al = new ArrayList<String>();
public static void main(String[] args)
{
String s = "abcd";
findsubsequences(s, ""); // Calling a function
System.out.println(al);
}
private static void findsubsequences(String s,
String ans)
{
if (s.length() == 0) {
al.add(ans);
return;
}
// We add adding 1st character in string
findsubsequences(s.substring(1), ans + s.charAt(0));
// Not adding first character of the string
// because the concept of subsequence either
// character will present or not
findsubsequences(s.substring(1), ans);
}
}
Python
# Below is the implementation of the above approach
def printSubsequence(input, output):
# Base Case
# if the input is empty print the output string
if len(input) == 0:
print(output, end=' ')
return
# output is passed with including the
# 1st character of input string
printSubsequence(input[1:], output+input[0])
# output is passed without including the
# 1st character of input string
printSubsequence(input[1:], output)
# Driver code
# output is set to null before passing in
# as a parameter
output = ""
input = "abcd"
printSubsequence(input, output)
# This code is contributed by Tharun Reddy
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG{
static void printSubsequence(string input,
string output)
{
// Base Case
// If the input is empty print the output string
if (input.Length == 0)
{
Console.WriteLine(output);
return;
}
// Output is passed with including
// the Ist character of
// Input string
printSubsequence(input.Substring(1),
output + input[0]);
// Output is passed without
// including the Ist character
// of Input string
printSubsequence(input.Substring(1),
output);
}
// Driver code
static void Main()
{
// output is set to null before passing
// in as a parameter
string output = "";
string input = "abcd";
printSubsequence(input, output);
}
}
// This code is contributed by SoumikMondal
Javascript
<script>
// JavaScript program for the above approach
// Find all subsequences
function printSubsequence(input, output)
{
// Base Case
// if the input is empty print the output string
if (input.length==0) {
document.write( output + "<br>");
return;
}
// output is passed with including
// the Ist character of
// Input string
printSubsequence(input.substring(1), output + input[0]);
// output is passed without
// including the Ist character
// of Input string
printSubsequence(input.substring(1), output);
}
// Driver code
// output is set to null before passing in as a
// parameter
var output = "";
var input = "abcd";
printSubsequence(input, output);
</script>
Time Complexity: O(n2^n) This is because, for a string of length n, we generate a total of 2^n sub-sequences.
Auxiliary Space : O(n) The recursive function call stack requires O(n) space for the worst case, where n is the length of the given string.
Further Optimization : Instead of generating a substring every-time, we can pass index as additional parameter and pass reference of the same string.
Incremental Approach
One by one fix characters and recursively generate all subsets starting from them. After every recursive call, we remove the last character so that the next permutation can be generated.
C++
#include <bits/stdc++.h>
using namespace std;
// s : Stores input string
// n : Length of s.
// curr : Stores current permutation
// index : Index in current permutation, curr
void printSubSeqRec(string s, int n, int index = -1,
string curr = "") {
// base case
if (index == n)
return;
// Print the current subsequence (including empty)
cout << curr << "\n";
for (int i = index + 1; i < n; i++) {
curr += s[i];
printSubSeqRec(s, n, i, curr);
// backtracking
curr = curr.erase(curr.size() - 1);
}
return;
}
// Generates power set in lexicographic order.
void printSubSeq(string s) {
printSubSeqRec(s, s.size());
}
// Driver code
int main() {
string s = "ab";
printSubSeq(s);
return 0;
}
Java
// Java program to generate power set in
// lexicographic order.
class GFG {
// str : Stores input string
// n : Length of str.
// curr : Stores current permutation
// index : Index in current permutation, curr
static void printSubSeqRec(String str, int n, int index,
String curr)
{
// base case
if (index == n) {
return;
}
if (curr != null && !curr.trim().isEmpty()) {
System.out.println(curr);
}
for (int i = index + 1; i < n; i++) {
curr += str.charAt(i);
printSubSeqRec(str, n, i, curr);
// backtracking
curr = curr.substring(0, curr.length() - 1);
}
}
// Generates power set in
// lexicographic order.
static void printSubSeq(String str)
{
int index = -1;
String curr = "";
printSubSeqRec(str, str.length(), index, curr);
}
// Driver code
public static void main(String[] args)
{
String str = "cab";
printSubSeq(str);
}
}
// This code is contributed by PrinciRaj1992
Python
# Python program to generate power set in lexicographic order.
# str: Stores input string
# n: Length of str.
# curr: Stores current permutation
# index: Index in current permutation, curr
def printSubSeqRec(str, n, index = -1, curr = ""):
# base case
if (index == n):
return
if (len(curr) > 0):
print(curr)
i = index + 1
while(i < n):
curr = curr + str[i]
printSubSeqRec(str, n, i, curr)
curr = curr[0:-1]
i = i + 1
# Generates power set in lexicographic order.
# function
def printSubSeq(str):
printSubSeqRec(str, len(str))
# // Driver code
str = "cab"
printSubSeq(str)
# This code is contributed by shinjanpatra
C#
// Include namespace system
using System;
// C# program to generate power set in
// lexicographic order.
public class GFG
{
// str : Stores input string
// n : Length of str.
// curr : Stores current permutation
// index : Index in current permutation, curr
public static void printSubSeqRec(String str, int n, int index, String curr)
{
// base case
if (index == n)
{
return;
}
if (curr != null && !(curr.Trim().Length == 0))
{
Console.WriteLine(curr);
}
for (int i = index + 1; i < n; i++)
{
curr += str[i];
GFG.printSubSeqRec(str, n, i, curr);
// backtracking
curr = curr.Substring(0,curr.Length - 1-0);
}
}
// Generates power set in
// lexicographic order.
public static void printSubSeq(String str)
{
var index = -1;
var curr = "";
GFG.printSubSeqRec(str, str.Length, index, curr);
}
// Driver code
public static void Main(String[] args)
{
var str = "cab";
GFG.printSubSeq(str);
}
}
// This code is contributed by mukulsomukesh
Javascript
<script>
// JavaScript program to generate power set in
// lexicographic order.
// str : Stores input string
// n : Length of str.
// curr : Stores current permutation
// index : Index in current permutation, curr
function printSubSeqRec(str,n,index = -1,curr = "")
{
// base case
if (index == n)
return;
if (curr.length>0) {
document.write(curr)
}
for (let i = index + 1; i < n; i++) {
curr += str[i];
printSubSeqRec(str, n, i, curr);
// backtracking
curr = curr.slice(0, - 1);
}
return;
}
// Generates power set in lexicographic
// order.
function printSubSeq(str)
{
printSubSeqRec(str, str.length);
}
// Driver code
let str = "cab";
printSubSeq(str);
</script>
Time Complexity: O(n * 2n), where n is the size of the given string
Auxiliary Space: O(n), due to recursive call stack
Using Binary Representation of Numbers from 0 to 2^n – 1
String = "abc"
All combinations of abc can be represented by all binary representation from 0 to (2^n - 1) where n is the size of the string . The following representation clears things up.
Note : We can also take zero into consideration which will eventually give us an empty set "", the only change in code will be starting loop from zero.
001 -> "c"
010 -> "b"
011 -> "bc
100 -> "a"
101 -> "ac"
110 -> "ab"
111 -> "abc"
As you can observe we get unique sub-sequences for every set-bit and thus no 2 combinations can be same as 2 numbers cannot have same binary representation.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
// Function to print all the power set
void printPowerSet(string &s) {
int n = pow(2, s.size());
for (int counter = 0; counter < n; counter++) {
for (int j = 0; j < s.size(); j++) {
// Check if jth bit in the counter is set
if (counter & (1 << j))
cout << s[j];
}
cout << endl;
}
}
/* Driver code */
int main() {
string s = "ab";
printPowerSet(s);
return 0;
}
Java
import java.util.*;
public class GFG {
//function to find where the bit is set
public static String print(String s , int i){
int j = 0;
String sub = "";
//finding the bit is set
while(i>0){
if((i & 1) == 1){
sub += s.charAt(j);
}
j++;
i = i>>1;
}
return sub;
}
//function to create sub-sets
public static List<String> createsubsets(String s){
List<String> res = new ArrayList<>();
for(int i = 0 ; i < (1<<s.length()) ; i++){
//each time we create a subsequence for corresponding binary representation
res.add(print(s,i));
}
return res;
}
//main function to call
public static void main(String args[])
{
String s = "abc";
// vector of strings to store all sub-sequences
List<String> print = createsubsets(s);
// print the subsets
for (int i = 0; i < print.size(); i++) {
for (int j = 0; j < print.get(i).length(); j++) {
System.out.print(print.get(i).charAt(j) + " ");
}
System.out.println();
}
}
}
// This code contributed by Srj_27
Python
def print_subset(s, i):
j = 0
sub = ""
#finding where the bit is set
while i > 0:
if i & 1:
sub += s[j] #pushing only when bit is set
j += 1 #always incrementing the index pointer
i = i >> 1
return sub
def createsubsets(s):
res = []
for i in range(1, (1 << len(s))):
#each time we create a subsequence for corresponding binary representation
res.append(print_subset(s, i))
return res
if __name__ == "__main__":
s = "abc"
#vector of strings to store all sub-sequences
subsets = createsubsets(s)
#print function
for subset in subsets:
for c in subset:
print(c, end=" ")
print()
# This code is contributed Shivam Tiwari
C#
using System;
using System.Collections.Generic;
namespace GFG
{
class Program
{
//function to find where the bit is set
public static string Print(string s, int i)
{
int j = 0;
string sub = "";
//finding the bit is set
while (i > 0)
{
if ((i & 1) == 1)
{
sub += s[j];
}
j++;
i = i >> 1;
}
return sub;
}
//function to create sub-sets
public static List<string> CreateSubsets(string s)
{
List<string> res = new List<string>();
for (int i = 0; i < (1 << s.Length); i++)
{
//each time we create a subsequence for corresponding binary representation
res.Add(Print(s, i));
}
return res;
}
static void Main(string[] args)
{
string s = "abc";
// list of strings to store all sub-sequences
List<string> print = CreateSubsets(s);
// print the subsets
for (int i = 0; i < print.Count; i++)
{
for (int j = 0; j < print[i].Length; j++)
{
Console.Write(print[i][j] + " ");
}
Console.WriteLine();
}
}
}
}
// This code contributed by Ajax
Javascript
// Function to extract a subsequence when the corresponding bit is set
function printSubset(s, i) {
let j = 0; // Index pointer to iterate through the string s
let sub = ""; // Resultant subsequence
// Finding where the bit is set
while (i > 0) {
if (i & 1) {
// Pushing only when the bit is set
sub += s[j];
}
j += 1; // Always incrementing the index pointer
i = i >> 1; // Right shift the number to get the next bit
}
return sub;
}
// Function to generate all possible sub-sequences
function createSubsets(s) {
let res = []; // Array to store all sub-sequences
for (let i = 1; i < (1 << s.length); i++) {
// Each iteration generates a sub-sequence for the corresponding binary representation
res.push(printSubset(s, i));
}
return res;
}
// Driver Code
const s = "abc"; // String input
const subsets = createSubsets(s); // Array of all sub-sequences
// Printing the sub-sequences
for (let subset of subsets) {
for (let c of subset) {
process.stdout.write(c + " ");
}
console.log();
}
Time Complexity: O(n* 2^n)
Auxiliary Space: O(n)
Similar Reads
Basics & Prerequisites
Data Structures
Array Data StructureIn this article, we introduce array, implementation in different popular languages, its basic operations and commonly seen problems / interview questions. An array stores items (in case of C/C++ and Java Primitive Arrays) or their references (in case of Python, JS, Java Non-Primitive) at contiguous
3 min read
String in Data StructureA string is a sequence of characters. The following facts make string an interesting data structure.Small set of elements. Unlike normal array, strings typically have smaller set of items. For example, lowercase English alphabet has only 26 characters. ASCII has only 256 characters.Strings are immut
2 min read
Hashing in Data StructureHashing is a technique used in data structures that efficiently stores and retrieves data in a way that allows for quick access. Hashing involves mapping data to a specific index in a hash table (an array of items) using a hash function. It enables fast retrieval of information based on its key. The
2 min read
Linked List Data StructureA linked list is a fundamental data structure in computer science. It mainly allows efficient insertion and deletion operations compared to arrays. Like arrays, it is also used to implement other data structures like stack, queue and deque. Hereâs the comparison of Linked List vs Arrays Linked List:
2 min read
Stack Data StructureA Stack is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). LIFO implies that the element that is inserted last, comes out first and FILO implies that the element that is inserted first
2 min read
Queue Data StructureA Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Tree Data StructureTree Data Structure is a non-linear data structure in which a collection of elements known as nodes are connected to each other via edges such that there exists exactly one path between any two nodes. Types of TreeBinary Tree : Every node has at most two childrenTernary Tree : Every node has at most
4 min read
Graph Data StructureGraph Data Structure is a collection of nodes connected by edges. It's used to represent relationships between different entities. If you are looking for topic-wise list of problems on different topics like DFS, BFS, Topological Sort, Shortest Path, etc., please refer to Graph Algorithms. Basics of
3 min read
Trie Data StructureThe Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this
15+ min read
Algorithms
Searching AlgorithmsSearching algorithms are essential tools in computer science used to locate specific items within a collection of data. In this tutorial, we are mainly going to focus upon searching in an array. When we search an item in an array, there are two most common algorithms used based on the type of input
2 min read
Sorting AlgorithmsA Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read
Introduction to RecursionThe process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. A recursive algorithm takes one step toward solution and then recursively call itself to further move. The algorithm stops once we reach the solution
14 min read
Greedy AlgorithmsGreedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a global optimum solution. At every step of the algorithm, we make a choice that looks the best at the moment. To make the choice, we sometimes sort the array so that we can always get
3 min read
Graph AlgorithmsGraph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Dynamic Programming or DPDynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Bitwise AlgorithmsBitwise algorithms in Data Structures and Algorithms (DSA) involve manipulating individual bits of binary representations of numbers to perform operations efficiently. These algorithms utilize bitwise operators like AND, OR, XOR, NOT, Left Shift, and Right Shift.BasicsIntroduction to Bitwise Algorit
4 min read
Advanced
Segment TreeSegment Tree is a data structure that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tree
3 min read
Pattern SearchingPattern searching algorithms are essential tools in computer science and data processing. These algorithms are designed to efficiently find a particular pattern within a larger set of data. Patten SearchingImportant Pattern Searching Algorithms:Naive String Matching : A Simple Algorithm that works i
2 min read
GeometryGeometry is a branch of mathematics that studies the properties, measurements, and relationships of points, lines, angles, surfaces, and solids. From basic lines and angles to complex structures, it helps us understand the world around us.Geometry for Students and BeginnersThis section covers key br
2 min read
Interview Preparation
Practice Problem