You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何还原Java中基于正则表达式的二进制字符串压缩结果?

如何还原基于正则表达式的二进制字符串压缩算法?

我使用了@tigrang提供的这段Java代码来压缩二进制字符串:

public static String compress_string(String inp) { 
    String compressed = ""; 
    Pattern pattern = Pattern.compile("([\\w])\\1*"); 
    Matcher matcher = pattern.matcher(inp); 
    while(matcher.find()) { 
        String group = matcher.group(); 
        if (group.length() > 1) 
            compressed += group.length() + ""; 
        compressed += group.charAt(0); 
    } 
    return compressed; 
}

但当我压缩6个连续的1(即字符串"111111",对应字符'p'的二进制)时,得到的输出是"3131"。现在我需要知道如何还原这种压缩操作,把压缩后的字符串转回原始的二进制字符串。


首先,我们先拆解这段压缩代码的核心逻辑,这样才能针对性地写出还原算法:

压缩代码的工作原理

这段代码的核心是用正则表达式([\w])\1*匹配连续重复的相同字符,然后对每个匹配到的字符序列做如下处理:

  • 如果序列长度大于1,就先拼接长度的字符串,再拼接字符本身;
  • 如果序列长度等于1,直接拼接字符。

正常情况下,输入"111111"应该得到"61",而你得到"3131",说明原始输入可能被拆成了两个连续的3个1序列(比如输入中间混入了不可见字符,或者正则匹配出现了异常),不过没关系,我们可以基于压缩后的字符串格式写出通用的还原逻辑。

还原算法的思路

压缩后的字符串是由数字+字符或单个字符组成的片段构成的。还原时需要:

  1. 遍历压缩后的字符串,区分出连续的数字部分和后续的字符部分;
  2. 对于每个片段:
    • 如果前面有数字,就把对应的字符重复数字次数;
    • 如果没有数字(即单个字符),就直接保留该字符;
  3. 把所有片段拼接起来,得到原始字符串。

注意:这里的数字可能是多位数(比如原始序列长度是12,压缩后会是"121"),所以还原时要把连续的数字字符当成一个整体处理。

还原代码实现(Java)

下面是对应这段压缩逻辑的还原代码,同时也能处理你遇到的"3131"这种拆分后的情况:

public static String decompress_string(String compressed) {
    StringBuilder decompressed = new StringBuilder();
    int i = 0;
    int len = compressed.length();
    
    while (i < len) {
        // 收集连续的数字字符
        StringBuilder numStr = new StringBuilder();
        while (i < len && Character.isDigit(compressed.charAt(i))) {
            numStr.append(compressed.charAt(i));
            i++;
        }
        // 防止越界(理论上压缩后的字符串不会出现这种情况)
        if (i >= len) break;
        
        char targetChar = compressed.charAt(i);
        i++;
        
        // 确定重复次数:有数字则用数字值,无数字则默认为1
        int repeatCount = numStr.length() > 0 ? Integer.parseInt(numStr.toString()) : 1;
        // 重复字符并添加到结果中
        for (int j = 0; j < repeatCount; j++) {
            decompressed.append(targetChar);
        }
    }
    return decompressed.toString();
}

测试你的例子

用这段还原代码处理"3131":

  • 第一个片段:数字"3" + 字符'1' → 生成"111";
  • 第二个片段:数字"3" + 字符'1' → 生成"111";
  • 拼接后得到"111111",正好是你原始的6个1的字符串。

如果是正常压缩得到的"61",这段代码也能正确还原成"111111",所以它是通用的。

额外排查建议

如果你想搞清楚为什么6个1会被压缩成"3131",可以检查原始输入字符串是否真的是连续的6个'1'——比如有没有可能中间混入了不可见的控制字符,导致正则匹配把它拆成了两个序列。你可以打印原始字符串每个字符的ASCII码来确认。

内容的提问来源于stack exchange,提问作者TheFlyBiker 420

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:46:58