一、题目描述
误码率是最常用的数据通信传输质量指标。它可以理解为"在多少位数据中出现一位差错"。
移动通信网络中的误码率主要是指比特误码率,其计算公式如下: 比特误码率=错误比特数/传输总比特数,
为了简单,我们使用字符串来标识通信的信息,一个字符错误了,就认为出现了一个误码
输入一个标准的字符串,和一个传输后的字符串,计算误码率
字符串会被压缩,
例:"2A3B4D5X1Z"表示"AABBBDDDDXXXXXZ"
用例会保证两个输入字符串解压后长度一致,解压前的长度不一定一致
每个生成后的字符串长度<100000000。
二、输入输出描述
输入描述
- 第一行:标准的字符串,每行字符串 (压缩后的) 长度<100000;
- 第二行:传输后的字符串,每行字符串 (压缩后的) 长度<100000。
输出描述
-
错误的字等数量/展开后的总长度
备注
注意:展开后的字符串不含数字
三、示例
|----|-----------|
| 输入 | 3A3B 2A4B |
| 输出 | 1/6 |
| 说明 | |
|----|-----------|
| 输入 | 5Y5Z 5Y5Z |
| 输出 | 0/10 |
| 说明 | |
|----|---------|
| 输入 | 4Y5Z 9Y |
| 输出 | 5/9 |
| 说明 | |
四、解题思路
- 核心思想
采用压缩字符串结构化解析 + 链表头部逐段对比 + 剩余长度复用 的策略,先将非结构化的压缩字符串转为可操作的ZipStr链表,再按顺序逐段对比字符和长度,统计差异与相同的可匹配长度,最终按指定格式输出结果。核心是结构化解析简化操作,逐段对比保证顺序一致性,剩余复用确保长度精准统计。
- 问题本质分析
- 表层问题:对两个压缩字符串进行对比,统计字符差异和相同的可匹配长度,按格式返回结果;
- 深层问题:
-
格式解析问题:压缩字符串是 "数字 + 字符" 的混合格式,直接对比无法区分数字和字符,需先结构化解析为 "次数 + 字符" 的单元,简化后续操作;
-
顺序对比问题:压缩字符串的字符顺序是固定的(从左到右),需按原顺序逐段对比,不能打乱顺序,链表的头部操作可完美保证顺序一致性;
-
长度匹配问题:两段字符的重复次数可能不一致,需取最小值作为可匹配长度,同时保留剩余长度继续参与对比,避免长度统计遗漏;
-
统计逻辑问题:需严格区分 "字符相同" 和 "字符不同" 的可匹配长度,分别累加后按固定格式拼接结果。
-
核心逻辑
- 结构化解析:将压缩字符串解析为
LinkedList<ZipStr>,把 "数字 + 字符" 的混合字符串转为结构化单元,每个单元包含明确的重复次数和对应字符,为后续对比提供清晰的数据结构; - 逐段顺序对比:以链表头部移除的方式,按压缩字符串的原始顺序逐段取出
ZipStr单元,保证对比顺序与字符串原始顺序一致; - 可匹配长度计算:对每一对
ZipStr单元,取重复次数的最小值作为可匹配长度,确保统计的是两段字符能相互匹配的最大长度; - 差异与相同统计:根据字符是否一致,将可匹配长度分别累加到
diff(差异)或same(相同); - 剩余长度复用:对超出可匹配长度的
ZipStr单元,更新剩余次数后放回原链表头部,继续参与下一轮对比,确保所有可匹配长度都被统计; - 结果拼接:按
diff/(diff+same)的格式拼接统计结果,返回最终字符串。
-
步骤拆解
-
压缩字符串结构化解析
- 对每个输入的压缩字符串,调用
getZipStrLink方法; - 遍历字符串,拼接数字字符为完整数字,遇到非数字字符时,创建
ZipStr单元(数字转为重复次数,非数字为对应字符),加入LinkedList; - 最终得到两个结构化的
ZipStr链表(link1和link2)。
- 对每个输入的压缩字符串,调用
-
初始化统计变量
- 初始化
diff=0(字符不同的可匹配长度总和)、same=0(字符相同的可匹配长度总和)。
- 初始化
-
链表头部逐段对比与统计
- 进入循环(终止条件:
link1为空):
- 分别从
link1和link2头部移除并获取ZipStr单元(zipStr1和zipStr2); - 计算可匹配长度:
compareCount = Math.min(zipStr1.num, zipStr2.num); - 字符对比:若
zipStr1.c != zipStr2.c,diff += compareCount;否则same += compareCount; - 剩余长度处理:
- 若
zipStr1.num > compareCount:更新zipStr1.num -= compareCount,放回link1头部,跳过后续zipStr2处理; - 若
zipStr2.num > compareCount:更新zipStr2.num -= compareCount,放回link2头部;
- 若
- 进入循环(终止条件:
-
结果拼接与返回
- 计算总可匹配长度:
total = diff + same; - 按
diff/total的格式拼接字符串,返回该结果。
- 计算总可匹配长度:
五、代码实现
java
import java.util.LinkedList;
import java.util.Scanner;
public class Main {
static class ZipStr {
int num;
char c;
public ZipStr(int num, char c) {
this.num = num;
this.c = c;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s1 = sc.nextLine();
String s2 = sc.nextLine();
System.out.println(getResult(s1, s2));
}
public static String getResult(String s1, String s2) {
LinkedList<ZipStr> link1 = getZipStrLink(s1);
LinkedList<ZipStr> link2 = getZipStrLink(s2);
int diff = 0;
int same = 0;
while (link1.size() > 0) {
ZipStr zipStr1 = link1.removeFirst();
ZipStr zipStr2 = link2.removeFirst();
int compareCount = Math.min(zipStr1.num, zipStr2.num);
if (zipStr1.c != zipStr2.c) {
diff += compareCount;
} else {
same += compareCount;
}
if (zipStr1.num > compareCount) {
zipStr1.num -= compareCount;
link1.addFirst(zipStr1);
continue;
}
if (zipStr2.num > compareCount) {
zipStr2.num -= compareCount;
link2.addFirst(zipStr2);
}
}
return diff + "/" + (diff + same);
}
public static LinkedList<ZipStr> getZipStrLink(String s) {
LinkedList<ZipStr> link = new LinkedList<>();
StringBuilder num = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c >= '0' && c <= '9') {
num.append(c);
} else {
link.add(new ZipStr(Integer.parseInt(num.toString()), c));
num = new StringBuilder();
}
}
return link;
}
}