【区块链】C语言编程实现三叉Merkle树

news2024/11/15 13:44:26

目录

      • 1. Merkle树简介
      • 2. 构建Merkle树
      • 3. 生成SPV路径
      • 4. 验证SPV路径
      • 5. 三叉Merkle树创建、SPV生成及验证总程序
      • 6. 程序运行结果

1. Merkle树简介

  如上图所示,Merkle 树的叶子节点为交易序列,对每一笔交易进行 Hash(SHA 256算法) 之后,然后对得到的 Hash 节点进行拼接再次进行 Hash 运算,如此递归直到递归至根节点。

  如上图所示 Merkle 树的优点在于可快速验证某个区块是否存在指定交易,如要验证 H k H_k Hk是否存在于该区块中,只要将 H L 、 H I J 、 H M N O P 、 H A B C D E F G H_L、H_{IJ}、H_{MNOP}、H_{ABCDEFG} HLHIJHMNOPHABCDEFG节点得到,然后从下到上不断 Hash,最后与根节点的 Hash 值进行比较,就可以快速判断交易是否在该区块中。

2. 构建Merkle树

  1. 头文件及Merkle节点类型
# include <iostream>
# include <functional>
# include<string>
using namespace std;
typedef struct MerkleNode {
	MerkleNode* Left;
	MerkleNode* Middle;
	MerkleNode* Right;
	MerkleNode* parent;
	size_t data;
};
struct MerkleTree {
	MerkleNode* RootNode;
}root;
  1. 创建三叉merkle所需函数
/* 创建merkle树 */
MerkleNode* queue[100000];
int front = 0, rear = 0, new_rear = 0;
int n;
// 字符串加密
size_t encrypt(string strInput)
{
	hash<string> Hash;
	size_t hashVal = Hash(strInput);
	return hashVal;
}

// size_t转换为字符串
string type_convert(size_t input)
{
	string output = to_string(input);
	return output;
}

// 字符串拼接
string concat(string one, string two,string three)
{
	string output = one + two + three;
	return output;
}

// 初始化叶子节点
void init_leaf_node(MerkleNode*& node,size_t data)
{
	node = (MerkleNode*)malloc(sizeof(MerkleNode));
	node->data = encrypt(type_convert(data));
	node->Left = NULL;
	node->Middle = NULL;
	node->Right = NULL;
}

// 对最后一个节点进行拷贝
MerkleNode* copy_node(MerkleNode* node)
{
	MerkleNode* new_node = (MerkleNode*)malloc(sizeof(MerkleNode));
	new_node->Left = NULL;
	new_node->Middle = NULL;
	new_node->Right = NULL;
	new_node->data = node->data;
	return new_node;
}

// 初始化分枝节点
void init_branch_node(MerkleNode* Left, MerkleNode* Middle, MerkleNode* Right)
{
	MerkleNode* node = (MerkleNode*)malloc(sizeof(MerkleNode));
	node->Left = Left;
	node->Middle = Middle;
	node->Right = Right;
	Left->parent = node;
	Middle->parent = node;
	Right->parent = node;
	node->data = encrypt(concat(type_convert(Left->data), type_convert(Middle->data), type_convert(Right->data)));
	queue[new_rear++] = node;
}

// 根据队列中的节点生成其父节点
void create_new_layer()
{
	// 补足剩余节点
	int remainder = rear % 3;
	int res = 0;
	if (remainder != 0)
	{
		res = 3 - remainder;
		MerkleNode* node = queue[rear - 1];
		for (int i = 0; i < res; i++)
		{
			queue[rear++] = copy_node(node);
		}
	}

	int loop = (rear + res) / 3;


	for (int i = 0; i < loop; i++)
	{
		MerkleNode* Left = queue[front++];
		MerkleNode* Middle = queue[front++];
		MerkleNode* Right = queue[front++];
		init_branch_node(Left, Middle, Right);
	}
	rear = new_rear;
	new_rear = 0;
	front = 0;
}

// 创建merkle树
void create_merkle_tree(MerkleTree*& root)
{
	while (rear != 1)
	{
		create_new_layer();
	}
	root = (MerkleTree*)malloc(sizeof(MerkleTree));
	root->RootNode = queue[rear-1];
	root->RootNode->parent = NULL;
}

// 输入数据
void init_data()
{
	cout << "请输入交易序列个数:";
	cin >> n;
	cout << "请输入每一笔交易(中间以空格隔开):";
	for (int i = 0; i < n; i++)
	{
		MerkleNode* node;
		size_t data;
		cin >> data;
		init_leaf_node(node, data);
		queue[rear++] = node;
	}
}

3. 生成SPV路径

SPV路径生成代码:

/*  生成SPV路径  */ 
size_t spv_queue[100010];
MerkleNode *sequence[100010];
int seq_front = 0, seq_rear = 0;
int spv_front = 0,spv_rear = 0;
int spv_flag[100010], flag_idx = 0;

void init_all_node_sequence(MerkleNode* node)
{
	sequence[++seq_rear] = node;
	while (seq_front != seq_rear)
	{
		MerkleNode* new_node = sequence[++seq_front];
		if (new_node->Left != NULL)
		{
			sequence[++seq_rear] = new_node->Left;
		}
		if (new_node->Middle != NULL)
		{
			sequence[++seq_rear] = new_node->Middle;
		}
		if (new_node->Right != NULL)
		{
			sequence[++seq_rear] = new_node->Right;
		}
	}
	seq_front = 0;
}

void init_spv_path(int idx,MerkleTree *root)
{
	MerkleNode* head_node = root->RootNode;
	init_all_node_sequence(head_node);

	int cnt;
	if (n % 3 == 0)
	{
		cnt = 3;
	}
	else if((n + 1) % 3 == 0) {
		cnt = n + 1;
	}
	else {
		cnt = n + 2;
	}
	int seq_idx = seq_rear - (cnt - idx);
	cout << "该交易的哈希值为:" << sequence[seq_idx]->data<< endl;

	MerkleNode* node = sequence[seq_idx];

	while (node->parent)
	{
		MerkleNode* parent = node->parent;
		if (node == parent->Left)
		{
			spv_flag[flag_idx++] = 0;
			spv_queue[++spv_rear] = parent->Middle->data;
			spv_queue[++spv_rear] = parent->Right->data;
		}
		else if (node == parent->Middle)
		{
			spv_flag[flag_idx++] = 1;
			spv_queue[++spv_rear] = parent->Left->data;
			spv_queue[++spv_rear] = parent->Right->data;
		}
		else {
			spv_flag[flag_idx++] = 2;
			spv_queue[++spv_rear] = parent->Left->data;
			spv_queue[++spv_rear] = parent->Middle->data;
		}
		node = node->parent;
	}

}

void print_spv_path(int idx)
{
	cout << "交易序列号" << idx << "的SPV路径为:";
	while (spv_front != spv_rear)
	{
		cout << spv_queue[++spv_front] << " ";
	}
	cout << endl;
	spv_front = 0;
	cout << "生成交易在其兄弟节点中的位置序列为(0为Left,1为Middle,2为Right):";
	for (int i = 0; i < flag_idx; i++)
	{
		cout << spv_flag[i] << " ";
	}
}

4. 验证SPV路径

SPV路径验证代码:

/* 验证SPV路径 */
size_t root_hash, spv_path[1010], hash_val;
int spv_length;
void judge_spv_path()
{
	cout << "请输入merkle树根节点哈希值:";
	cin >> root_hash;

	cout << "请输入SPV路径长度:";
	cin >> spv_length;
	cout << "请输入SPV路径(中间用空格隔开):";
	for (int i = 0; i < spv_length; i++)
	{
		cin >> spv_path[i];
	}

	int pos_cnt, pos_sqe[100010];
	cout << "请输入交易位置序列个数:";
	cin >> pos_cnt;
	cout << "请输入交易位置序列(中间用空格隔开):";
	for (int i = 0; i < pos_cnt; i++)
	{
		cin >> pos_sqe[i];
	}

	cout << "请输入要查询的交易哈希值:";
	cin >> hash_val;

	int path_idx = 0, pos_idx = 0;
	while (path_idx != spv_length)
	{
		size_t one = spv_path[path_idx++];
		size_t two = spv_path[path_idx++];
		if (pos_sqe[pos_idx] == 0)
		{
			hash_val = encrypt(concat(type_convert(hash_val), type_convert(one), type_convert(two)));
		}
		else if (pos_sqe[pos_idx] == 1)
		{
			hash_val = encrypt(concat(type_convert(one), type_convert(hash_val), type_convert(two)));
		}
		else {
			hash_val = encrypt(concat(type_convert(one), type_convert(two), type_convert(hash_val)));
		}
		pos_idx++;
	}
	cout << "SPV计算得到的哈希值为:" << hash_val <<endl;
	cout << "头节点哈希值为:" << root_hash << endl;
	if (hash_val == root_hash)
	{
		cout << "SPV路径验证成功!!!" << endl << endl << endl;
	}
}

5. 三叉Merkle树创建、SPV生成及验证总程序

# define _CRT_SECURE_NO_DEPRECATE
# include <iostream>
# include <functional>
# include<string>
using namespace std;
typedef struct MerkleNode {
	MerkleNode* Left;
	MerkleNode* Middle;
	MerkleNode* Right;
	MerkleNode* parent;
	size_t data;
};
struct MerkleTree {
	MerkleNode* RootNode;
}root;

/* 创建merkle树 */
MerkleNode* queue[100000];
int front = 0, rear = 0, new_rear = 0;
int n;
// 字符串加密
size_t encrypt(string strInput)
{
	hash<string> Hash;
	size_t hashVal = Hash(strInput);
	return hashVal;
}

// size_t转换为字符串
string type_convert(size_t input)
{
	string output = to_string(input);
	return output;
}

// 字符串拼接
string concat(string one, string two,string three)
{
	string output = one + two + three;
	return output;
}

// 初始化叶子节点
void init_leaf_node(MerkleNode*& node,size_t data)
{
	node = (MerkleNode*)malloc(sizeof(MerkleNode));
	node->data = encrypt(type_convert(data));
	node->Left = NULL;
	node->Middle = NULL;
	node->Right = NULL;
}

// 对最后一个节点进行拷贝
MerkleNode* copy_node(MerkleNode* node)
{
	MerkleNode* new_node = (MerkleNode*)malloc(sizeof(MerkleNode));
	new_node->Left = NULL;
	new_node->Middle = NULL;
	new_node->Right = NULL;
	new_node->data = node->data;
	return new_node;
}

// 初始化分枝节点
void init_branch_node(MerkleNode* Left, MerkleNode* Middle, MerkleNode* Right)
{
	MerkleNode* node = (MerkleNode*)malloc(sizeof(MerkleNode));
	node->Left = Left;
	node->Middle = Middle;
	node->Right = Right;
	Left->parent = node;
	Middle->parent = node;
	Right->parent = node;
	node->data = encrypt(concat(type_convert(Left->data), type_convert(Middle->data), type_convert(Right->data)));
	queue[new_rear++] = node;
}

// 根据队列中的节点生成其父节点
void create_new_layer()
{
	// 补足剩余节点
	int remainder = rear % 3;
	int res = 0;
	if (remainder != 0)
	{
		res = 3 - remainder;
		MerkleNode* node = queue[rear - 1];
		for (int i = 0; i < res; i++)
		{
			queue[rear++] = copy_node(node);
		}
	}

	int loop = (rear + res) / 3;


	for (int i = 0; i < loop; i++)
	{
		MerkleNode* Left = queue[front++];
		MerkleNode* Middle = queue[front++];
		MerkleNode* Right = queue[front++];
		init_branch_node(Left, Middle, Right);
	}
	rear = new_rear;
	new_rear = 0;
	front = 0;
}

// 创建merkle树
void create_merkle_tree(MerkleTree*& root)
{
	while (rear != 1)
	{
		create_new_layer();
	}
	root = (MerkleTree*)malloc(sizeof(MerkleTree));
	root->RootNode = queue[rear-1];
	root->RootNode->parent = NULL;
}

// 输入数据
void init_data()
{
	cout << "请输入交易序列个数:";
	cin >> n;
	cout << "请输入每一笔交易(中间以空格隔开):";
	for (int i = 0; i < n; i++)
	{
		MerkleNode* node;
		size_t data;
		cin >> data;
		init_leaf_node(node, data);
		queue[rear++] = node;
	}
}



/*  生成SPV路径  */ 
size_t spv_queue[100010];
MerkleNode *sequence[100010];
int seq_front = 0, seq_rear = 0;
int spv_front = 0,spv_rear = 0;
int spv_flag[100010], flag_idx = 0;

void init_all_node_sequence(MerkleNode* node)
{
	sequence[++seq_rear] = node;
	while (seq_front != seq_rear)
	{
		MerkleNode* new_node = sequence[++seq_front];
		if (new_node->Left != NULL)
		{
			sequence[++seq_rear] = new_node->Left;
		}
		if (new_node->Middle != NULL)
		{
			sequence[++seq_rear] = new_node->Middle;
		}
		if (new_node->Right != NULL)
		{
			sequence[++seq_rear] = new_node->Right;
		}
	}
	seq_front = 0;
}

void init_spv_path(int idx,MerkleTree *root)
{
	MerkleNode* head_node = root->RootNode;
	init_all_node_sequence(head_node);

	int cnt;
	if (n % 3 == 0)
	{
		cnt = 3;
	}
	else if((n + 1) % 3 == 0) {
		cnt = n + 1;
	}
	else {
		cnt = n + 2;
	}
	int seq_idx = seq_rear - (cnt - idx);
	cout << "该交易的哈希值为:" << sequence[seq_idx]->data<< endl;

	MerkleNode* node = sequence[seq_idx];

	while (node->parent)
	{
		MerkleNode* parent = node->parent;
		if (node == parent->Left)
		{
			spv_flag[flag_idx++] = 0;
			spv_queue[++spv_rear] = parent->Middle->data;
			spv_queue[++spv_rear] = parent->Right->data;
		}
		else if (node == parent->Middle)
		{
			spv_flag[flag_idx++] = 1;
			spv_queue[++spv_rear] = parent->Left->data;
			spv_queue[++spv_rear] = parent->Right->data;
		}
		else {
			spv_flag[flag_idx++] = 2;
			spv_queue[++spv_rear] = parent->Left->data;
			spv_queue[++spv_rear] = parent->Middle->data;
		}
		node = node->parent;
	}

}

void print_spv_path(int idx)
{
	cout << "交易序列号" << idx << "的SPV路径为:";
	while (spv_front != spv_rear)
	{
		cout << spv_queue[++spv_front] << " ";
	}
	cout << endl;
	spv_front = 0;
	cout << "生成交易在其兄弟节点中的位置序列为(0为Left,1为Middle,2为Right):";
	for (int i = 0; i < flag_idx; i++)
	{
		cout << spv_flag[i] << " ";
	}
}

/* 验证SPV路径 */
size_t root_hash, spv_path[1010], hash_val;
int spv_length;
void judge_spv_path()
{
	cout << "请输入merkle树根节点哈希值:";
	cin >> root_hash;

	cout << "请输入SPV路径长度:";
	cin >> spv_length;
	cout << "请输入SPV路径(中间用空格隔开):";
	for (int i = 0; i < spv_length; i++)
	{
		cin >> spv_path[i];
	}

	int pos_cnt, pos_sqe[100010];
	cout << "请输入交易位置序列个数:";
	cin >> pos_cnt;
	cout << "请输入交易位置序列(中间用空格隔开):";
	for (int i = 0; i < pos_cnt; i++)
	{
		cin >> pos_sqe[i];
	}

	cout << "请输入要查询的交易哈希值:";
	cin >> hash_val;

	int path_idx = 0, pos_idx = 0;
	while (path_idx != spv_length)
	{
		size_t one = spv_path[path_idx++];
		size_t two = spv_path[path_idx++];
		if (pos_sqe[pos_idx] == 0)
		{
			hash_val = encrypt(concat(type_convert(hash_val), type_convert(one), type_convert(two)));
		}
		else if (pos_sqe[pos_idx] == 1)
		{
			hash_val = encrypt(concat(type_convert(one), type_convert(hash_val), type_convert(two)));
		}
		else {
			hash_val = encrypt(concat(type_convert(one), type_convert(two), type_convert(hash_val)));
		}
		pos_idx++;
	}
	cout << "SPV计算得到的哈希值为:" << hash_val <<endl;
	cout << "头节点哈希值为:" << root_hash << endl;
	if (hash_val == root_hash)
	{
		cout << "SPV路径验证成功!!!" << endl << endl << endl;
	}
}



int main()
{

	cout << "================================================  Merkle树构建部分  ===================================================" << endl << endl;
	init_data();	// 数据初始化(输入相关数据)
	// 生成 Merkle 树
	MerkleTree* root;
	create_merkle_tree(root);
	cout << "merkle树根哈希值为:" << root->RootNode->data << endl;
	cout << "merkle树构建完成!" << endl << endl << endl;

	// 生成SPV路径
	cout << "================================================  SPV路径生成部分  ===================================================" << endl << endl;
	int idx;
	cout << "请输入交易序号(i):";
	cin >> idx;
	init_spv_path(idx, root);
	print_spv_path(idx);
	cout << endl << endl << endl;

	// 验证SPV路径
	cout << "================================================  SPV路径验证部分  ===================================================" << endl << endl;
	judge_spv_path();

	return 0;
}

6. 程序运行结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1549177.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vivado 在远程主机上启动作业、ISE命令图、实施类别,战略描述和指令映射

在远程主机上启动作业 一旦配置了远程主机&#xff0c;使用它们启动Vivado作业就很容易了。下图显示了启动运行对话框。启动跑步时&#xff0c;选择“在远程上启动跑步”hosts或Launch在群集上运行&#xff0c;然后选择特定的群集。这些作业将使用您的要执行的预配置设置。 作业…

针对COT控制模式下低ESR电容造成次谐波振荡问题的片内斜波补偿方案

COT模式&#xff1a;MOS管固定导通时间控制模式&#xff0c;关断时间由输出反馈电压与内部基准源的相较值决定。 RBCOT控制模式&#xff1a;Ripple-Based COT基于纹波的固定导通时间控制方法&#xff0c;特别的是环路控制部分主要有固定导通时间发生装置及比较器组成。RBCOT控…

DreamPolisher、InternLM2 、AniArtAvatar、PlainMamba、AniPortrait

本文首发于公众号&#xff1a;机器感知 DreamPolisher、InternLM2 、AniArtAvatar、PlainMamba、AniPortrait DreamPolisher: Towards High-Quality Text-to-3D Generation via Geometric Diffusion We present DreamPolisher, a novel Gaussian Splatting based method wit…

PPP实验

一、实验拓扑图 二、实验要求 1、R1和R2使用PPP链路直连&#xff0c;R2和R3把2条PPP链路捆绑为PPP MP直连 2、按照图示配置IP地址 3、R2对R1的PPP进行单向chap验证 4、R2和R3的PPP进行双向chap验证 三、实验步骤 1、PPP MP&#xff1a; &#xff08;1&#xff09;R2配置&#x…

C语言从入门到实战----数据在内存中的存储

1. 整数在内存中的存储 在讲解操作符的时候&#xff0c;我们就讲过了下⾯的内容&#xff1a; 整数的2进制表⽰⽅法有三种&#xff0c;即 原码、反码和补码 有符号的整数&#xff0c;三种表⽰⽅法均有符号位和数值位两部分&#xff0c;符号位都是⽤0表⽰“正”&#xff0c;⽤…

dji esdk开发(4)SDK互联互通(与云端进行小数据通信)

Edge SDK 提供接口可以通过上云 API 与和机场建立连接的云端服务器进行小数据交互,即向云端服务器发送自定义小数据与接收来自云端服务器的自定义小数据。 注意: 使用该接口发送和接收数据上下行通道最大带宽不应超过 0.5Mb/S。 1、云端低速通道介绍 使用自定义小数据通道需…

C++类和对象、面向对象编程 (OOP)

文章目录 一、封装1.抽象、封装2.类和对象(0)学习视频(1)类的构成(2)三种访问权限(3)struct和class的区别(4)私有的成员变量、共有的成员函数(5)类内可以直接访问私有成员&#xff0c;不需要经过对象 二、继承三、多态1.概念2.多态的满足条件3.多态的使用条件4.多态原理剖析5.纯…

详细描述红黑树如何左旋、右旋(图文结合)

红黑树 首先要理解二叉查找树 二叉查找树&#xff08;BST&#xff09;具备什么特性呢&#xff1f; 左子树上所有结点的值均小于或等于它的根结点的值。 右子树上所有结点的值均大于或等于它的根结点的值。 左、右子树也分别为二叉排序树。 二叉查找树是二分查找的思想&…

vben admin路由跳转拿不到param参数问题

vben admin路由跳转拿不到param参数问题 问题原因&#xff1a; 也就是说&#xff0c;从Vue Router的2022-8-22 这次更新后&#xff0c;我们使用上面的方式在新页面无法获取&#xff1a; vue也给我们提出了解决方案&#xff1a; ​ 1.使用 query 的方式传参 ​ 2.将参数放…

Linux项目自动化构建工具make和makefile

前言 前面我们对yum、vim、gcc/g做了介绍&#xff0c;本期我们再来介绍一个好用的工具&#xff0c;就是make和makefile! 本期内容介绍 什么是make和makefile makefile文件内容的解释 make执行makefile的原理 我们想要的makefile 一、什么是make 和 makefile ? make是一条指令…

DVB-S系统仿真学习

DVB-S系统用于卫星电视信号传输&#xff0c;发送端框图如下所示 扰码 实际数字通信中&#xff0c;载荷数据的码元会出现长连0或长连1的情况&#xff0c;不利于接收端提取时钟信号&#xff0c;同时会使得数据流中含有大量的低频分量&#xff0c;使得QPSK调制器的相位长时间不变…

Python算法100例-4.6 歌星大奖赛

完整源代码项目地址&#xff0c;关注博主私信源代码后可获取 1.问题描述2.问题分析3.算法设计4.确定程序框架5.完整的程序6.问题拓展7.知识点补充 1&#xff0e;问题描述 在歌星大奖赛中&#xff0c;有10个评委为参赛的选手打分&#xff0c;分数为1&#xff5e;100分。选手最…

金融投贷通(金融投资+贷款通)项目准备

金融投贷通&#xff08;金融投资贷款通&#xff09;项目准备 专业术语投资专业术语本息专业术语还款专业术语项目介绍三个子系统技术架构核心流程发布借款标投资业务 项目实施测试流程测试步骤 专业术语 投资专业术语 案例&#xff1a;张三借给李四5W&#xff0c;约定期满1年后…

MySQL 高级语句(二)

一、子查询 1.1 相同表子查询 1.2 不同表/多表子查询 1.3 子查询的应用 1.3.1 语法 1.3.2 insert 子查询 1.3.3 update 子查询 1.3.4 delete 子查询 1.4 exists 关键字 1.4.1 true 1.4.2 false 1.5 as别名 二、视图 2.1 视图和表的区别和联系 2.1.1 区别 2.1.2 …

【面试必备】针对一个案例,怎么测试

思考角度 测试用例设计万能公式功能测试&#xff08;最重要&#xff09;界面测试易用性测试性能测试安全性测试兼容性测试容错性测试 常见案例物品类水杯笔 软件类微信发送朋友圈功能 测试用例设计万能公式 在面试中经常会遇到的一类题是&#xff0c;给你一个具体的产品&#…

《Attention Is All You Need》

参考&#xff1a; Attention Is All You Need 论文解读:Attention is All you need Transformer模型中的attention结构作用是什么&#xff1f; 如何最简单、通俗地理解Transformer&#xff1f; Transformer 新型神经网络&#xff0c;基于注意力机制 的 编码器-解码器 的序列处…

数据分析web可视化神器---streamlit框架,无需懂前端也能搭建出精美的web网站页面

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属的专栏&#xff1a;数据分析系统化教学&#xff0c;零基础到进阶实战 景天的主页&#xff1a;景天科技苑 文章目录 Streamlit什么是streamli…

国内ip地址推荐,畅享网络新体验!

在数字化时代&#xff0c;IP地址不仅是网络连接的基石&#xff0c;也是互联网产业发展的重要标志。国内作为全球互联网市场的重要参与者&#xff0c;拥有众多IP地址资源。虎观代理小二旨在探索并推荐一些国内IP地址&#xff0c;分析它们的价值所在&#xff0c;并探讨如何更好地…

抖音电商“达人客服”产品上线啦!超多作者邀你一起“321上客服”!

有问题别自己克服&#xff0c;来抖音电商找“达人客服” 当代年轻人购物&#xff0c;正在从机智省变成理智购。越来越多的人在达人直播间购物&#xff0c;看重的不止是优惠力度&#xff0c;还有服务保障。 为了帮助达人更好地服务用户&#xff0c;抖音电商上线了「达人客服」…

BERT模型中句子Tokenize和ID转换的过程

当我们使用BERT或其他类似的预训练语言模型时&#xff0c;将句子转换为token的过程通常涉及以下几个步骤&#xff1a; 初始化Tokenizer&#xff1a;首先&#xff0c;我们需要导入相应的Tokenizer类&#xff0c;并根据需求选择合适的预训练模型进行初始化。 分词&#xff08;To…