Skip to content
Advertisement

String compression and decompression for data set that can be nested

My input is a compressed string of the format number[string] and the decompressed output form should be the string written number times. For example:

3[abc]4[ab]c = abcabcabcababababc

2[3[a]b] = aaabaaab.

My brute force approach in Java:

public class CompresnDecompresn {

    public static void main(String[] args) {

        String s="3[abc]4[ab]c";
        for (int i = 0; i<s.length(); i++)  {
            if(s.charAt(i)==']') {
                int j=i-1;
                while(true)  {
                    if(s.charAt(j)=='[') {
                        break;
                    }
                    j--;
                }
                int k=j-1;
                while(true) {
                    if(k<0) {
                        break;
                    }
                    int m=(int)s.charAt(k);
                    if(m<48 || m>57) {
                        break;
                    }
                    k--;
                }
                k++;
                int freq=Integer.parseInt(s.substring(k, j));
                String snippet=s.substring(j+1,i);
                String temp="";

                for (int l = 0; l < freq; l++) {
                    temp+=snippet;
                }
                s=s.substring(0,k)+temp+s.substring(i+1);
            }
        }        
        System.out.println(s);                
    }    
}

Can I get some better approach with less cost?

Advertisement

Answer

We actually want to find the strings in [] and repeat it n times which is specified before the []. But the problem is these strings are nested. So when we call the function that reads the string in[] it should call itself again when it hits a new []. Hence this leads to a recursive solution and we loop through the input string only once.

public class StringDecomposer {

    public String process(String input) {

        StringBuilder result = new StringBuilder();

        decompres(input, 0, result);

        return result.toString();
    }

    private int decompres(String input, int ofset, StringBuilder result) {

        StringBuilder rpt = new StringBuilder();
        StringBuilder current = new StringBuilder();

        while(ofset < input.length()) {

            if(input.charAt(ofset) == '[') {
                ofset = decompres(input, ofset+1, current);
                repeat(rpt, current);
                result.append(current);
                rpt.delete(0, rpt.length());
                current.delete(0, current.length());
            }
            else if(input.charAt(ofset) == ']') {
                break;
            }
            else if(input.charAt(ofset) > 47 && 
                    input.charAt(ofset) < 58) {
                rpt.append(input.charAt(ofset));
            }
            else {
                current.append(input.charAt(ofset));
            }
            ofset++;
        }
        result.append(current);
        return ofset;
    }

    private void repeat(StringBuilder rpt, StringBuilder input) {

        if(rpt.length() > 0) {
            StringBuilder current = new StringBuilder(input);
            int times = Integer.parseInt(rpt.toString());
            for(int i = 1; i < times; i++) {
                input.append(current);
            }
        }
    }
}
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement