【2025刷题笔记】- TLV解码
刷题笔记合集🔗
TLV解码
问题描述
TLV编码是按[Tag Length Value]格式进行编码的,一段码流中的信元用Tag标识,Tag在码流中唯一不重复,Length表示信元Value的长度,Value表示信元的值。
码流以某信元的Tag开头,Tag固定占一个字节,Length固定占两个字节,字节序为小端序。
现给定TLV格式编码的码流,以及需要解码的信元Tag,请输出该信元的Value。
输入码流的16进制字符中,不包括小写字母,且要求输出的16进制字符串中也不要包含小写字母;码流字符串的最大长度不超过50000个字节。
输入格式
输入的第一行为一个字符串,表示待解码信元的 。
输入的第二行为一个字符串,表示待解码的16进制码流,字节之间用空格分隔。
输出格式
输出一个字符串,表示待解码信元以16进制表示的 。
样例输入
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
数据范围
| 样例 | 解释说明 |
|---|---|
| 样例1 | 需要解析的信元的Tag是31,从码流的起始处开始匹配,第一个信元的Tag是32,信元长度为1(01 00,小端序表示为1);第二个信元的Tag是90,其长度为2;第三个信元的Tag是30,其长度为3;第四个信元的Tag是31,其长度为2(02 00),所以返回长度后面的两个字节即可,即32 33。 |
- 输入的码流不包含小写字母
- 输出的字符串也不能包含小写字母
- 码流字符串的最大长度不超过50000个字节
题解
这道题目主要考察对TLV编码格式的理解和解析能力。TLV是Tag-Length-Value的缩写,这种编码方式在网络协议中很常见,如ASN.1编码。
首先明确题目要点:
- Tag占1个字节,用于标识不同信元
- Length占2个字节,使用小端序,标识Value的长度
- Value根据Length指定的长度存储实际数据
解题思路很直接:从码流开始依次解析每个信元,检查Tag是否匹配我们要找的值,如果找到就输出对应的Value。
我们可以按照以下步骤处理:
- 读取待查找的Tag值
- 从码流起始位置开始解析
- 对每个信元:
- 读取Tag值(1个字节)
- 读取Length值(2个字节,需要考虑小端序)
- 如果当前Tag与目标Tag匹配,则返回后面Length个字节作为Value
- 否则跳过当前信元的Value部分,继续处理下一个信元
时间复杂度是O(n),其中n是码流的长度。我们只需要遍历一次码流。空间复杂度是O(1),只需要常数级别的额外空间存储临时变量。
对于给定的样例,解析过程为:
- 读取Tag=31
- 第一个信元:Tag=32,Length=1,Value=AE,不匹配,继续
- 第二个信元:Tag=90,Length=2,Value=01 02,不匹配,继续
- 第三个信元:Tag=30,Length=3,Value=AB 32 31,不匹配,继续
- 第四个信元:Tag=31,Length=2,Value=32 33,匹配目标Tag,返回Value=32 33
这种线性扫描的方法对于这个问题是最优解,因为我们必须按顺序解析每个信元才能找到目标信元的位置。
参考代码
- Python
import sys
input = lambda:sys.stdin.readline().strip()
# 读取输入
target = input()
stream = input().split()
# 查找目标Tag的值
def find_tag_value():
i = 0
while i < len(stream):
# 获取当前Tag
curr_tag = stream[i]
i += 1
# 获取Length (小端序,需要翻转)
len_bytes = [stream[i], stream[i+1]]
i += 2
# 将小端序转换为长度值
length =
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专栏收集并整理了一些刷题笔记
查看19道真题和解析