Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 递归字符串解压缩_Java_Algorithm_Recursion_Nested_Compression - Fatal编程技术网

Java 递归字符串解压缩

Java 递归字符串解压缩,java,algorithm,recursion,nested,compression,Java,Algorithm,Recursion,Nested,Compression,我正在尝试解压缩如下所示的字符串: 输入:4(ab) 输出:abababab 输入:11ab 输出:AAAAAAB 输入:2(3b3(ab)) 输出:BBBABBBAB 使用下面的递归方法,上面的示例都能正确显示,但当我输入以下内容时会出现问题: 输入:4(ab)a 预期产出:阿巴巴 输入:2(3b3(ab))a 预期产量:BBBABABBBABA 我意识到在返回声明中出现的问题是“返回重复”。在其当前状态下,递归将继续,直到到达输入字符串的末尾,即使在结束括号之后也是如此。基本上,我不知道如何

我正在尝试解压缩如下所示的字符串:

输入:4(ab)

输出:abababab

输入:11ab

输出:AAAAAAB

输入:2(3b3(ab))

输出:BBBABBBAB

使用下面的递归方法,上面的示例都能正确显示,但当我输入以下内容时会出现问题:

输入:4(ab)a

预期产出:阿巴巴

输入:2(3b3(ab))a

预期产量:BBBABABBBABA

我意识到在返回声明中出现的问题是“返回重复”。在其当前状态下,递归将继续,直到到达输入字符串的末尾,即使在结束括号之后也是如此。基本上,我不知道如何让它在到达结束括号时中断,然后在有任何剩余时继续。在2(3b3(ab))a中,它应该返回2*(3b3(ab))+a,现在它返回2*(3b3(ab))a。非常感谢您的任何帮助,因为我无法理解

public static String decompress(String compressedText) throws Exception
{
   //BASE CASE 
    if(compressedText.length() == 1)
    {
        if(compressedText.charAt(0) == ')')
        {
            System.out.println("1: " + compressedText);
            return "";
        }
        else
        {
            System.out.println("2: " + compressedText);
            return compressedText;
        }

    }
    //END BASECASE


    if(compressedText.charAt(0) == '(')
    {
        System.out.println("3: " + compressedText);
        return decompress(compressedText.substring(1));        
    }


    //IF DOUBLE DIGIT
    if(Character.isDigit(compressedText.charAt(0)) == true && Character.isDigit(compressedText.charAt(1)) == true)
    {
        if(compressedText.charAt(3) != '(')
        {
            System.out.println("4: " + compressedText);
            int i = Integer.parseInt(compressedText.substring(0,2));
            String repeated = new String(new char[i]).replace("\0", compressedText.substring(2,3));  
            return repeated + decompress(compressedText.substring(3));
        }
        else
        {
            System.out.println("5: " + compressedText);
            int i = Integer.parseInt(compressedText.substring(0,2));
            String repeated = new String(new char[i]).replace("\0", decompress(compressedText.substring(2)));
            return repeated;
        }

    }
    //END DOUBLE DIGIT



    //IF SINGLE DIGIT
    if (Character.isDigit(compressedText.charAt(0)) == true)
    {
        if(compressedText.charAt(1) !='(')
        {
            System.out.println("6: " + compressedText);
            int i = Integer.parseInt(compressedText.substring(0,1));
            String repeated = new String(new char[i]).replace("\0", compressedText.substring(1,2));  
            return repeated + decompress(compressedText.substring(2)); 
        }
        else
        {
            System.out.println("7: " + compressedText);
            int i = Integer.parseInt(compressedText.substring(0,1));
            String repeated = new String(new char[i]).replace("\0", decompress(compressedText.substring(1)));
            return repeated;
        }

    }
    //END SINGLE DIGIT

    //IF RIGHT PARENTHESIS
    if (compressedText.charAt(0) == ')')
    {
        if (compressedText.charAt(1) != ')')
        {
            System.out.println("8: " + compressedText);
            return "";
        }
        else
        {
            System.out.println("9: " + compressedText);
            return  decompress(compressedText.substring(1));

        }

    }
    //END 

        System.out.println("10: " + compressedText);
        return compressedText.charAt(0)+decompress(compressedText.substring(1));

}

我注意到的一点是,在输出
“8:
后返回
时,您正在“丢失”最后一个“a”。在这个位置上,也应该处理拖尾字符,但是您不能简单地将它们返回到那里,既不能直接返回,也不能通过解压缩返回,因为这样会导致
bbbababababababababa

遗憾的是,我没有找到一个基于您的代码返回正确值的解决方案(我猜您如何将部分处理过的文本放入递归中有一些奇怪的行为,但我不确定……)

然而,我考虑了如何解决这个压缩问题,并提出了两个非递归的解决方案。也许它们可以帮助您改进解决方案。旁注:我的解决方案假设字符串格式良好,即它没有任何不匹配的括号等。 (我使用了一个重复函数,我把它放在了答案的末尾。)

第一个解决方案使用正则表达式,搜索数字和以下部分(一个字符或不包含括号的括号括起来的部分)。通过这种方式,括号和单字符解压缩从内部到外部进行处理

public static String decompressWithRegex(String s) {
    if ((s == null) || (s.length() == 0)) {
        return s;
    }
    // pattern for finding number with either bracket-enclosed, char-only part or single char
    Pattern p = Pattern.compile("(\\d+)((?:[^\\d\\(\\)]{1})|(?:\\([^\\d\\(\\)]+\\)))");
    String tmp = s;
    Matcher m = p.matcher(tmp);
    // start searching
    while (m.find(0)) {
        // first capture group returns count
        int count = Integer.parseInt(m.group(1));
        // second group is string to repeat (if it's bracket-enclosed, then remove brackets)
        String what = m.group(2).replace("(", "").replace(")", "");
        // build replacement part
        String replacePart = repeat(what, count);
        // replace it
        tmp = m.replaceFirst(replacePart);
        // reset matcher (source of matcher is now the new string)
        m.reset(tmp);
    }
    return tmp;
}
第二个解决方案不使用正则表达式。相反,它对如何处理解压缩进行了一些假设:

  • 任何不跟在括号内的零件后面的数字都可以直接输入 就地解压,这是先完成的
  • 通过查找第一个闭合支架来处理支架封闭零件
  • 然后从后面开始搜索开口括号
  • 这会让你重复这个部分
  • 左括号应该有一个数字,然后搜索和分析
  • 现在,我们有了所有的信息,更换的部分是建立和放置在正确的地方
  • 然后搜索下一个结束括号(如果有),并按上述方式处理
  • 如果没有右括号,字符串将被解压缩
代码:

用于重复字符串的实用程序方法:

public static String repeat(String what, int times) {
    if ((times <= 0) || (what == null) || (what.length() == 0)) {
        return "";
    }
    StringBuilder buffer = new StringBuilder(times * what.length());
    for (int i = 0; i < times; i++) {
        buffer.append(what);
    }
    return buffer.toString();
}
公共静态字符串重复(字符串内容,整数倍){

如果((times使用一个元组作为递归的返回值,它除了提供累积字符串外还提供右括号的索引:

index 0 1 2 3 4 5 6 7 8 9 10
str   2 ( 3 b 3 ( a b ) ) a

  f(0)

  => 2 * f(1)[0] add f(f(1)[1] + 1)  // f(1)[1] is the closing index 

    f(1) => 3 * b + 3 * f(5)[0] add f(f(5)[1] + 1)

    => f(5) returns (ab,8)

    f(1) => bbb + ababab add f(9) // str[9] is closing parenthesis

    => f(1) returns (bbbababab,9)

  => 2 * bbbababab add f(10)

  => bbbabababbbbabababa
JavaScript代码:

var示例='2(3b3(ab)2(cd3(fg)))ab2(gh2(xz))';
console.log(示例);
log(解压缩(示例));
函数解压缩{
//返回元组[累加器,右括号索引]
函数f(i){
累计风险=“”,
mult=“”,
curr='';
//在此级别中累积所有附加组
而(i!==s.length){
//右括号
如果(s[i]==')'){
//添加最后一次解压缩
如果(当前!=''){
累计+=自定义复制(当前、多个);
}
//退出此呼叫
返回[累计,i];
}
//字符是一个数字
如果(!isNaN(parseInt(s[i])){
//添加以前的解压缩
如果(当前!=''){
累计+=自定义复制(当前、多个);
curr='';
mult=s[i];
}否则{
mult+=s[i];
}
i++;
//性格就是性格
}否则如果(s[i]!=='('){
curr+=s[i];
i++;
//附加群
}如果(s[i]=='('){
//递归调用
[tempAccum,index]=f(i+1);
accum+=定制复制(tempAccum、mult);
mult='';
i=指数+1;
}
}
返回累计+自定义复制(当前、多个);
}
//初始化递归
返回f(0);
}
函数customReplicate(str,times){
返回新数组(次==''?1:parseInt(次))
.填充(str).连接(“”);

}
我意识到这是一个Java问题,但在用Java实现之前,我通常会编写一个小的Ruby代码来测试一个想法。如果有人感兴趣,下面是我的代码:

def decompress(str)
  str.gsub!(/(\d+)([a-z])/i){$2*$1.to_i}       # Replace every subtring like "3b" and "11a".
  while str.include?('(') do
    str.sub!(/(\d+)\(([a-z]+)\)/){$2*$1.to_i}  # Replace the first inner group found
  end
  str
end

puts decompress("4(ab)")       == "abababab"
puts decompress("11ab")        == "aaaaaaaaaaab"
puts decompress("2(3b3(ab))")  == "bbbabababbbbababab"
puts decompress("4(ab)a")      == "ababababa"
puts decompress("2(3b3(ab))a") == "bbbabababbbbabababa"
#=> true, true, true, true, true

@jCoder在他的第一个示例中写了几乎完全相同的东西,因此无需重新发明轮子!

对于
2(3b3(ab))的预期输出一个
bbbababbbaba
有趣的问题。你可以使用递归下降解析器和一点BNF语法。然后你可以在大约10分钟内完成代码。好的,添加了JavaScript代码示例。很好。我真的很喜欢第一个示例。我想我理解其中的逻辑,但我的java知识不足以实际实现它。我尝试添加一个for循环,当遇到一个数字后跟一个括号时,它会“向前看”。返回括号中包含的压缩部分+接下来的内容。类似于:return repeated(直到“)”)+“compressedtext(后面的所有内容”)))。问题是,如果输入是代码中使用的字符串,则
def decompress(str)
  str.gsub!(/(\d+)([a-z])/i){$2*$1.to_i}       # Replace every subtring like "3b" and "11a".
  while str.include?('(') do
    str.sub!(/(\d+)\(([a-z]+)\)/){$2*$1.to_i}  # Replace the first inner group found
  end
  str
end

puts decompress("4(ab)")       == "abababab"
puts decompress("11ab")        == "aaaaaaaaaaab"
puts decompress("2(3b3(ab))")  == "bbbabababbbbababab"
puts decompress("4(ab)a")      == "ababababa"
puts decompress("2(3b3(ab))a") == "bbbabababbbbabababa"
#=> true, true, true, true, true