目录
题目部分
|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 题目 | TLV编码 |
| 题目说明 | TLV编码是按[Tag Length Value]格式进行编码的,一段码流中的信元用Tag标识,Tag在码流中唯一不重复,Length表示信元Value的长度,Value表示信元的值。 码流以某信元的Tag开头,Tag固定占一个字节,Length固定占两个字节,字节序为小端序。 现给定TLV格式编码的码流,以及需要解码的信元Tag,请输出该信元的Value。 输入码流的16机制字符中,不包括小写字母,且要求输出的16进制字符串中也不要包含小写字母;码流字符串的最大长度不超过50000个字节。 |
| 输入描述 | 输入的第一行为一个字符串,表示待解码信元的Tag; 输入的第二行为一个字符串,表示待解码的16进制码流,字节之间用空格分隔。 |
| 输出描述 | 输出一个字符串,表示待解码信元以16进制表示的Value。 |
| 补充说明 | 无 |
| --------------------------------------------------------------------------------------- ||
| 示例 | |
| 示例1 | |
| 输入 | 31 32 01 00 AE 90 02 00 01 02 30 03 00 AB 32 31 31 02 00 32 33 33 01 00 CC |
| 输出 | 32 33 |
| 说明 | 需要解析的信元的Tag是31,从码流的起始处开始匹配,Tag为32的信元长度为1(01 00,小端序表示为1); 第二个信元的Tag是90,其长度为2; 第三个信元的Tag是30,其长度为3; 第四个信元的Tag是31,其长度为2(02 00),所以返回长度后面的两个字节即可,即32 33。 |
解析与思路
题目解读:
题目中,输入的第二行是TLV信息流。TLV信息流由多个信元组成,而每个信元由Tag、Length、Value组成;输入第一行是Tag,即需要从第二行数据流中输出信元 Value 所对应的 Tag。
题目要求从第二行的多个信元中,找到第一行的Tag所对应的信元。然后输出此信元的Value。
在输入示例中,第一行指定了信元的Tag是31,第二行输入的信息流包含了5个信元,依次为32、90、30、31、33。我们找到Tag为31的信元,它为 31 02 00 32 33,其中 31 是Tag,02 00(即2)是长度,那么其紧跟的2个字节 32 33 为Value,所以最终的结果输出为 32 33。
分析与思路:
此题根据指定的tag,从信息流中找到对应的信息员,输出其value即可,并不涉及太复杂的逻辑算法。实现如下:
- 记录第一行输入的数字,设为变量 tag。
- 逐一遍历第二行输入的信息流。遍历时,先判断第一个输入是否等于tag:
- 如果等于 tag,则继续遍历接下来的2个字节,(根据小端序)计算长度,设为变量 length,然后输出接下来的 length 个字节,即为最终输出。输出后退出程序。
- 如果不等于tag,则继续遍历接下来的2个字节,计算长度,设为变量length,然后跳过接下来的 length 个字节,然后继续步骤 2。
此算法只需要遍历一次第二行的输入,时间复杂度为O(n),只需要2个额外的辅助变量,空间复杂度为O(1)。
代码实现
Java代码
java
import java.util.Scanner;
/**
* TLV解码
* @since 2023.09.04
* @version 0.1
* @author Frank
*
*/
public class LTV_Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 第一行输入的tag
String tag = sc.nextLine();
// 第二行输入的TLV数据流
String stream = sc.nextLine();
String[] input = stream.split(" ");
int i = 0;
while (i < input.length) {
String tagTmp = input[i];
String lengthStr = input[i + 2] + input[i + 1];
int length = Integer.parseInt(lengthStr, 16);
// 已找到,输出
if ( !tagTmp.equals( tag )) {
// 没有找到Tag,略过,寻找下一个
i += ( 3 + length);
continue;
}
StringBuilder outputSB = new StringBuilder();
for (int j = 0; j < length; j++) {
outputSB.append(input[i + j + 3]);
if (j != length - 1) {
outputSB.append(" ");
}
}
System.out.println(outputSB.toString());
return;
}
}
}
JavaScript代码
javascript
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function() {
let input = [];
while (line = await readline()) {
input.push(line);
}
// 第一行数据
var tag = input[0];
// 第二行数据转换成数组
var ltvs = input[1].split(" ");
var i = 0;
while (i < ltvs.length) {
var tagTmp = ltvs[i];
var lengthStr = ltvs[i + 2] + ltvs[i + 1];
var length = parseInt(lengthStr, 16);
// 已找到,输出
if (tagTmp != tag ) {
// 没有找到Tag,略过,寻找下一个
i += (3 + length);
continue;
}
var output = "";
for (var j = 0; j < length; j++) {
output += ( ltvs[i + j + 3]);
if (j != length - 1) {
output += " ";
}
}
console.log( output );
return;
}
}();
(完)