package com.freetymekiyan.algorithms.level.medium;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* Given an encoded string, return it's decoded string.
* <p>
* The encoding rule is: k[encoded_string], where the encoded_string inside the square brackets is being repeated
* exactly k times. Note that k is guaranteed to be a positive integer.
* <p>
* You may assume that the input string is always valid; No extra white spaces, square brackets are well-formed, etc.
* <p>
* Furthermore, you may assume that the original data does not contain any digits and that digits are only for those
* repeat numbers, k. For example, there won't be input like 3a or 2[4].
* <p>
* Examples:
* <p>
* s = "3[a]2[bc]", return "aaabcbc".
* s = "3[a2[c]]", return "accaccacc".
* s = "2[abc]3[cd]ef", return "abcabccdcdcdef".
* <p>
* Tags: Depth-first Search, Stack
*/
public class DecodeString {
/**
* Stack.
* Use two stacks to save current level information:
* One is the # of repeat times, the other is the pattern so far.
* For nested brackets, think about current level and the previous level.
* When enter from previous level to current level, we save the information of previous level.
* Both # of times to repeat and the pattern accumulated so far.
* When current level is finished, pop count and last pattern from the stack.
* Concatenate current level decode result with previous level.
*/
public String decodeString(String s) {
Deque<String> res = new ArrayDeque<>();
Deque<Integer> count = new ArrayDeque<>();
String decode = "";
int num = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (Character.isDigit(c)) {
num = 10 * num + c - '0';
} else if (c == '[') {
count.push(num);
num = 0;
res.push(decode);
decode = "";
} else if (c == ']') {
String tmp = decode;
decode = res.pop();
for (int j = count.pop(); j > 0; j--) {
decode += tmp;
}
} else {
decode += c;
}
}
return decode;
}
}