Decode a string recursively encoded as count followed by substring
An encoded string s is given, the task is to decode it. See examples to understand the pattern in which string is encoded .
Examples:
Input: s = "3[b2[ca]]"
Output: "bcacabcacabcaca"
Explanation: 1. inner substring "2[ca]" breakdown into "caca".
2. now , new string becomes "3[bcaca]"
3. similarly "3[bcaca]" becomes "bcacabcacabcaca " which is final result.Input: s = "2[ab]"
Output: "abab"Input: s = "2[ab]a"
Output: "ababa"
Table of Content
[Approach 1] Using Two Stacks - O(n) Time and O(n) Space
The idea is to use two stacks, one for integers and another for characters.
Now, traverse the string,
- Whenever we encounter any number, push it into the integer stack and in case of any alphabet (a to z) or open bracket ('['), push it on the character stack.
- Whenever any close bracket (']') is encountered, pop the characters from the character stack until open bracket ('[') is found in the stack. Also, pop the top element from the integer stack, say n. Now make a string repeating the popped character n number of time. Now, push all character of the string in the stack.
- After traversing whole string, integer stack will be empty and last string which will be formed will be the given result.
Illustration:
// C++ program to decode a string recursively
// encoded as count followed substring
#include <iostream>
#include <stack>
#include <string>
using namespace std;
// Function to decode the pattern string 's'
string decodedString(string &s) {
stack<int> numStack;
stack<char> charStack;
string temp = "";
string res = "";
for (int i = 0; i < s.length(); i++) {
int cnt = 0;
// If Digit, convert it into number and
// push it into integerstack.
if (s[i] >= '0' && s[i] <= '9') {
while (s[i] >= '0' && s[i] <= '9') {
cnt = cnt * 10 + s[i] - '0';
i++;
}
i--;
numStack.push(cnt);
}
// If closing bracket ']' is encountered
else if (s[i] == ']') {
temp = "";
cnt = numStack.top();
numStack.pop();
// pop element till opening bracket '[' is not found in the
// character stack.
while (charStack.top() != '[') {
temp = charStack.top() + temp;
charStack.pop();
}
charStack.pop();
// Repeating the popped string 'temp' count number of times.
for (int j = 0; j < cnt; j++)
res = res.append(temp);
// Push it in the character stack.
for (int j = 0; j < res.length(); j++)
charStack.push(res[j]);
res = "";
}
else
charStack.push(s[i]);
}
// Pop all the element, make a string and return.
while (!charStack.empty()) {
res = charStack.top() + res;
charStack.pop();
}
return res;
}
int main() {
string s = "3[b2[ca]]";
cout << decodedString(s) << endl;
return 0;
}
// Java program to decode a string recursively
// encoded as count followed by a substring
import java.util.Stack;
class GfG {
// Function to decode the pattern string 's'
static String decodedString(String s) {
Stack<Integer> numStack = new Stack<>();
Stack<Character> charStack = new Stack<>();
String temp = "";
StringBuilder res = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
int cnt = 0;
// If Digit, convert it into a number and
// push it into the integer stack.
if (Character.isDigit(s.charAt(i))) {
while (Character.isDigit(s.charAt(i))) {
cnt = cnt * 10 + (s.charAt(i) - '0');
i++;
}
i--;
numStack.push(cnt);
}
// If closing bracket ']' is encountered
else if (s.charAt(i) == ']') {
temp = "";
cnt = numStack.pop();
// Pop elements till the opening bracket '[' is found
// in the character stack.
while (charStack.peek() != '[') {
temp = charStack.pop() + temp;
}
charStack.pop(); // Remove '['
// Repeating the popped string 'temp' count number of times.
StringBuilder repeated = new StringBuilder();
for (int j = 0; j < cnt; j++) {
repeated.append(temp);
}
// Push it into the character stack.
for (int j = 0; j < repeated.length(); j++) {
charStack.push(repeated.charAt(j));
}
} else {
charStack.push(s.charAt(i));
}
}
// Pop all the elements, make a string, and return.
while (!charStack.isEmpty()) {
res.insert(0, charStack.pop());
}
return res.toString();
}
public static void main(String[] args) {
String s = "3[b2[ca]]";
System.out.println(decodedString(s));
}
}
# Python program to decode a string recursively
# encoded as count followed substring
# Function to decode the pattern string 's'
def decodedString(s):
numStack = []
charStack = []
temp = ""
res = ""
i = 0
while i < len(s):
cnt = 0
# If Digit, convert it into number and
# push it into integer stack.
if s[i].isdigit():
while i < len(s) and s[i].isdigit():
cnt = cnt * 10 + int(s[i])
i += 1
i -= 1
numStack.append(cnt)
# If closing bracket ']' is encountered
elif s[i] == ']':
temp = ""
cnt = numStack.pop()
# Pop element till opening bracket '[' is not found
# in the character stack.
while charStack[-1] != '[':
temp = charStack.pop() + temp
charStack.pop()
# Repeating the popped string 'temp' count number of times.
res = temp * cnt
# Push it in the character stack.
for c in res:
charStack.append(c)
res = ""
else:
charStack.append(s[i])
i += 1
# Pop all the elements, make a string and return.
while charStack:
res = charStack.pop() + res
return res
if __name__ == "__main__":
s = "3[b2[ca]]"
print(decodedString(s))
// C# program to decode a string recursively
// encoded as count followed by a substring
using System;
using System.Collections.Generic;
using System.Text;
class GfG {
// Function to decode the pattern string 's'
static string decodedString(string s) {
Stack<int> numStack = new Stack<int>();
Stack<char> charStack = new Stack<char>();
string temp = "";
StringBuilder res = new StringBuilder();
for (int i = 0; i < s.Length; i++) {
int cnt = 0;
// If Digit, convert it into a number and
// push it into the integer stack.
if (char.IsDigit(s[i])) {
while (char.IsDigit(s[i])) {
cnt = cnt * 10 + (s[i] - '0');
i++;
}
i--;
numStack.Push(cnt);
}
// If closing bracket ']' is encountered
else if (s[i] == ']') {
temp = "";
cnt = numStack.Pop();
// Pop elements till the opening bracket '[' is found
// in the character stack.
while (charStack.Peek() != '[') {
temp = charStack.Pop() + temp;
}
charStack.Pop(); // Remove '['
// Repeating the popped string 'temp' count number of times.
StringBuilder repeated = new StringBuilder();
for (int j = 0; j < cnt; j++) {
repeated.Append(temp);
}
// Push it into the character stack.
foreach (char c in repeated.ToString()) {
charStack.Push(c);
}
} else {
charStack.Push(s[i]);
}
}
// Pop all the elements, make a string, and return.
while (charStack.Count > 0) {
res.Insert(0, charStack.Pop());
}
return res.ToString();
}
static void Main(string[] args) {
string s = "3[b2[ca]]";
Console.WriteLine(decodedString(s));
}
}
// JavaScript program to decode a string recursively
// encoded as count followed substring
function decodedString(s) {
const numStack = [];
const charStack = [];
let temp = "";
let res = "";
for (let i = 0; i < s.length; i++) {
let cnt = 0;
// If Digit, convert it into number and
// push it into integer stack.
if (!isNaN(s[i])) {
while (!isNaN(s[i])) {
cnt = cnt * 10 + (s[i] - '0');
i++;
}
i--;
numStack.push(cnt);
}
// If closing bracket ']' is encountered
else if (s[i] === ']') {
temp = "";
cnt = numStack.pop();
// Pop element till opening bracket '[' is not found
// in the character stack.
while (charStack[charStack.length - 1] !== '[') {
temp = charStack.pop() + temp;
}
charStack.pop();
// Repeating the popped string 'temp' count number of times.
res = temp.repeat(cnt);
// Push it in the character stack.
for (const c of res) {
charStack.push(c);
}
res = "";
}
else {
charStack.push(s[i]);
}
}
// Pop all the elements, make a string and return.
while (charStack.length > 0) {
res = charStack.pop() + res;
}
return res;
}
// Driver Code
const s = "3[b2[ca]]";
console.log(decodedString(s));
Output
bcacabcacabcaca
[Approach 2] Using Single Stack - O(n) Time and O(n) Space
In this approach, we use a single stack to store both characters and digits. Instead of maintaining a separate integer stack for storing repetition counts, we store the digits directly in the main stack. The key observation is that the number always appears before the opening bracket
'['
. This allows us to retrieve it later without needing an extra stack.
Below are the detailed steps of implementation.
- Initialize an empty stack.
- Traverse the string:
- Push characters onto the stack until
']'
is encountered. - When
']'
is found:- Pop characters to form the substring until
'['
is found, then remove'['
. - Extract the preceding number from the stack and convert it to an integer.
- Repeat the substring and push the expanded result back onto the stack.
- Pop characters to form the substring until
- Push characters onto the stack until
- After traversal, pop all characters from the stack, reverse them, and return the final decoded string.
// C++ program to decode a string recursively encoded
// as count followed substring Using Single Stack
#include <iostream>
#include <stack>
#include <algorithm>
using namespace std;
string decodeString(string &s) {
stack<char> st;
// Traverse the input string
for (int i = 0; i < s.length(); i++) {
// Push characters into the stack until ']' is encountered
if (s[i] != ']') {
st.push(s[i]);
}
// Decode when ']' is found
else {
string temp;
// Pop characters until '[' is found
while (!st.empty() && st.top() != '[') {
temp.push_back(st.top());
st.pop();
}
reverse(temp.begin(), temp.end()); // Reverse extracted string
// Remove '[' from the stack
st.pop();
string num;
// Extract the number (repetition count) from the stack
while (!st.empty() && isdigit(st.top())) {
num = st.top() + num;
st.pop();
}
// Convert extracted number to integer
int number = stoi(num);
string repeat;
// Repeat the extracted string 'number' times
for (int j = 0; j < number; j++)
repeat.append(temp);
// Push the expanded string back onto the stack
for (char c : repeat)
st.push(c);
}
}
string res;
// Pop all characters from stack to form the final result
while (!st.empty()) {
res.push_back(st.top());
st.pop();
}
// Reverse to get the correct order
reverse(res.begin(), res.end());
return res;
}
int main() {
string str = "3[b2[ca]]";
cout << decodeString(str);
return 0;
}
// Java program to decode a string recursively encoded
// as count followed substring Using Single Stack
import java.util.Stack;
class GfG {
static String decodeString(String s) {
Stack<Character> st = new Stack<>();
// Traverse the input string
for (int i = 0; i < s.length(); i++) {
// Push characters into the stack until ']' is encountered
if (s.charAt(i) != ']') {
st.push(s.charAt(i));
}
// Decode when ']' is found
else {
StringBuilder temp = new StringBuilder();
// Pop characters until '[' is found
while (!st.isEmpty() && st.peek() != '[') {
temp.append(st.pop());
}
temp.reverse(); // Reverse extracted string
// Remove '[' from the stack
st.pop();
StringBuilder num = new StringBuilder();
// Extract the number (repetition count) from the stack
while (!st.isEmpty() && Character.isDigit(st.peek())) {
num.insert(0, st.pop());
}
// Convert extracted number to integer
int number = Integer.parseInt(num.toString());
StringBuilder repeat = new StringBuilder();
// Repeat the extracted string 'number' times
for (int j = 0; j < number; j++)
repeat.append(temp);
// Push the expanded string back onto the stack
for (char c : repeat.toString().toCharArray())
st.push(c);
}
}
StringBuilder res = new StringBuilder();
// Pop all characters from stack to form the final result
while (!st.isEmpty()) {
res.append(st.pop());
}
// Reverse to get the correct order
res.reverse();
return res.toString();
}
public static void main(String[] args) {
String str = "3[b2[ca]]";
System.out.println(decodeString(str));
}
}
# python program to decode a string recursively encoded
# as count followed substring Using Single Stack
def decodeString(s: str) -> str:
st = []
# Traverse the input string
for i in range(len(s)):
# Push characters into the stack until ']' is encountered
if s[i] != ']':
st.append(s[i])
# Decode when ']' is found
else:
temp = []
# Pop characters until '[' is found
while st and st[-1] != '[':
temp.append(st.pop())
temp.reverse() # Reverse extracted string
# Remove '[' from the stack
st.pop()
num = []
# Extract the number (repetition count) from the stack
while st and st[-1].isdigit():
num.insert(0, st.pop())
# Convert extracted number to integer
number = int("".join(num))
repeat = "".join(temp) * number # Repeat the extracted string 'number' times
# Push the expanded string back onto the stack
st.extend(repeat)
# Pop all characters from stack to form the final result
return "".join(st)
if __name__ == "__main__":
str_val = "3[b2[ca]]"
print(decodeString(str_val))
// C# program to decode a string recursively encoded
// as count followed substring Using Single Stack
using System;
using System.Collections.Generic;
using System.Text;
class GfG {
static string decodeString(string s) {
Stack<char> st = new Stack<char>();
// Traverse the input string
for (int i = 0; i < s.Length; i++) {
// Push characters into the stack until ']' is encountered
if (s[i] != ']') {
st.Push(s[i]);
}
// Decode when ']' is found
else {
StringBuilder temp = new StringBuilder();
// Pop characters until '[' is found
while (st.Count > 0 && st.Peek() != '[') {
temp.Insert(0, st.Pop()); // Insert at beginning to simulate reverse
}
// Remove '[' from the stack
st.Pop();
StringBuilder num = new StringBuilder();
// Extract the number (repetition count) from the stack
while (st.Count > 0 && char.IsDigit(st.Peek())) {
num.Insert(0, st.Pop());
}
// Convert extracted number to integer
int number = int.Parse(num.ToString());
StringBuilder repeat = new StringBuilder();
// Repeat the extracted string 'number' times
for (int j = 0; j < number; j++)
repeat.Append(temp);
// Push the expanded string back onto the stack
foreach (char c in repeat.ToString())
st.Push(c);
}
}
StringBuilder res = new StringBuilder();
// Pop all characters from stack to form the final result
while (st.Count > 0) {
// Insert at beginning to maintain order
res.Insert(0, st.Pop());
}
return res.ToString();
}
static void Main(string[] args) {
string str = "3[b2[ca]]";
Console.WriteLine(decodeString(str));
}
}
// Javascript program to decode a string recursively encoded
// as count followed substring Using Single Stack
function decodedString(s) {
let stack = [];
let temp = "";
let res = "";
for (let i = 0; i < s.length; i++) {
let cnt = 0;
// If number, convert it into number
if (s[i] >= '0' && s[i] <= '9') {
while (s[i] >= '0' && s[i] <= '9') {
cnt = cnt * 10 + (s[i] - '0');
i++;
}
i--;
// converting the integer into
// char in order to store in a stack.
stack.push(cnt.toString());
}
// If closing bracket ']', pop element until
// '[' opening bracket is not found in the
// stack.
else if (s[i] === ']') {
temp = "";
while (stack[stack.length - 1] !== '[') {
temp = stack.pop() + temp;
}
// Now top element of stack is '['.
// Let's pop it to get the integer
stack.pop();
// Top element of stack will give the integer in char form.
// converting into integer.
cnt = parseInt(stack.pop(), 10);
// Repeating the popped string 'temp' count number of times.
for (let j = 0; j < cnt; j++) {
res += temp;
}
// Push it in the character stack.
for (let j = 0; j < res.length; j++) {
stack.push(res[j]);
}
res = "";
}
else {
stack.push(s[i]);
}
}
// Pop all the element, make a string and return.
while (stack.length > 0) {
res = stack.pop() + res;
}
return res;
}
// Driver code
const s = "3[b2[ca]]";
console.log(decodedString(s));
Output
bcacabcacabcaca
[Alternate Approach] Without Using Stack - O(n) Time and O(n) Space
The given problem can be solved by traversing the encoded string character by character and maintaining a result string. Whenever a closing bracket is encountered, we can extract the substring enclosed within the corresponding opening bracket, and the number of times it needs to be repeated, and append the resulting string to the current result. We can continue this process until we reach the end of the input string.
// C++ implementation to decode the string
// without using stack
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
// Function to decode the given encoded string
string decodedString(string &s) {
// Declare a string variable to store the decoded
// string
string res = "";
// Traverse the encoded string character by character.
for (int i = 0; i < s.length(); i++) {
// If the current character is not a clostring
// bracket, append it to the result string.
if (s[i] != ']') {
res.push_back(s[i]);
}
// If the current character is a closing bracket
else {
// Create a temporary string to store the
// substring within the corresponding opening
// bracket.
string temp = "";
while (!res.empty() && res.back() != '[') {
temp.push_back(res.back());
res.pop_back();
}
// Reverse the temporary string to obtain the
// correct substring.
reverse(temp.begin(), temp.end());
// Remove the opening bracket from the result
// string.
res.pop_back();
// Extract the preceding number and convert it
// to an integer.
string num = "";
while (!res.empty() && res.back() >= '0' && res.back() <= '9') {
num.push_back(res.back());
res.pop_back();
}
reverse(num.begin(), num.end());
int p = stoi(num);
// Append the substring to the result string,
// repeat it to the required number of times.
while (p--) {
res.append(temp);
}
}
}
// Return the decoded string.
return res;
}
int main() {
string s = "3[b2[ca]]";
cout << decodedString(s);
return 0;
}
// Java implementation to decode the given string without stack
import java.util.*;
class GfG {
// Function to decode given encoded string
static String decodedString(String s) {
StringBuilder res = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
// If the current character is not a closing
// bracket, append it to the result string.
if (s.charAt(i) != ']') {
res.append(s.charAt(i));
}
// If the current character is a closing bracket
else {
// Create a temporary string to store
// the substring within the corresponding
// opening bracket.
StringBuilder temp = new StringBuilder();
while (res.length() > 0
&& res.charAt(res.length() - 1)
!= '[') {
temp.insert(
0, res.charAt(res.length() - 1));
res.deleteCharAt(res.length() - 1);
}
// Remove the opening bracket from the
// result string.
res.deleteCharAt(res.length() - 1);
// Extract the preceding number and convert
// it to an integer.
StringBuilder num = new StringBuilder();
while (res.length() > 0
&& Character.isDigit(
res.charAt(res.length() - 1))) {
num.insert(
0, res.charAt(res.length() - 1));
res.deleteCharAt(res.length() - 1);
}
int p = Integer.parseInt(num.toString());
// Append the substring to the result
// string, repeat it to the required number
// of times.
for (int j = 0; j < p; j++) {
res.append(temp.toString());
}
}
}
return res.toString();
}
public static void main(String[] args) {
String s = "3[b2[ca]]";
System.out.println(decodedString(s));
}
}
# Function to decode given encoded string without using stack.
def decodedString(s):
res = ""
for i in range(len(s)):
# If the current character is not a closing bracket, append it to the result string.
if s[i] != ']':
res += s[i]
# If the current character is a closing bracket
else:
# Create a temporary string to store
#the substring within the corresponding opening bracket.
temp = ""
while res and res[-1] != '[':
temp = res[-1] + temp
res = res[:-1]
# Remove the opening bracket from the result string.
res = res[:-1]
# Extract the preceding number and convert it to an integer.
num = ""
while res and res[-1].isdigit():
num = res[-1] + num
res = res[:-1]
p = int(num)
# Append the substring to the result
#string, repeat it to the required number of times.
res += temp * p
return res
if __name__ == "__main__":
s = "3[b2[ca]]"
print(decodedString(s))
// C# implementation to decode the string without stack
using System;
using System.Text;
class GfG {
// Function to decode the given encoded string
static string decodedString(string s) {
StringBuilder res = new StringBuilder();
for (int i = 0; i < s.Length; i++) {
// If the current character is not a
// closing bracket, append it to the result string.
if (s[i] != ']')
res.Append(s[i]);
// If the current character is a closing bracket
else {
// Create a StringBuilder to store the substring
// within the corresponding opening bracket.
StringBuilder temp = new StringBuilder();
while (res.Length > 0 && res[res.Length - 1] != '[') {
temp.Insert(0, res[res.Length - 1]);
res.Length--;
}
// Remove the opening bracket from the result string.
res.Length--;
// Extract the preceding number and convert it to an integer.
StringBuilder num = new StringBuilder();
while (res.Length > 0 && char.IsDigit(res[res.Length - 1])) {
num.Insert(0, res[res.Length - 1]);
res.Length--;
}
int p = int.Parse(num.ToString());
// Append the substring to the result string,
// repeat it to the required number of times.
for (int j = 0; j < p; j++)
res.Append(temp.ToString());
}
}
// Return the decoded string.
return res.ToString();
}
static void Main(string[] args) {
string s = "3[b2[ca]]";
Console.WriteLine(decodedString(s));
}
}
// Function to decode the given encoded string
// without using stack
function decodedString(s) {
let res = "";
for (let i = 0; i < s.length; i++) {
// If the current character is not a closing
// bracket, append it to the result string.
if (s[i] !== ']') {
res += s[i];
}
// If the current character is a closing bracket
else {
// Create a temporary string to store
// the substring within the corresponding opening bracket.
let temp = "";
while (res.length > 0 && res[res.length - 1] !== '[') {
temp = res[res.length - 1] + temp;
res = res.slice(0, -1);
}
// Remove the opening bracket from the result string.
res = res.slice(0, -1);
// Extract the preceding number and convert it to an integer.
let num = "";
while (res.length > 0 && !isNaN(res[res.length - 1])) {
num = res[res.length - 1] + num;
res = res.slice(0, -1);
}
let p = parseInt(num);
// Append the substring to the result string,
// repeat it to the required number of times.
res += temp.repeat(p);
}
}
// Return the decoded string.
return res;
}
// Driver Code
let s = "3[b2[ca]]";
console.log(decodedString(s));
Output
bcacabcacabcaca