计算字符串的相似度---编辑距离

本文深入探讨了编辑距离(Levenshtein距离)的概念及其应用场景,提供了递归、动态规划及带备忘录的递归三种实现方式,并附带完整的C++代码示例。

编辑距离:

又称Levenshtein距离(也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。

例如将kitten一字转成sitting:

sitten(k→s)

sittin(e→i)

sitting(→g)


利用递归来求解算法:

#include <iostream>

using namespace std;

int cacDistance(const char *lhs, int lBegin, int lEnd,
				const char *rhs, int rBegin, int rEnd)
{
	if (lBegin > lEnd)
	{
		if (rBegin > rEnd)
			return 0;
		else
			return rEnd - rBegin + 1;
	}
	if (rBegin > rEnd)
	{
		if (lBegin > lEnd)
			return 0;
		else
			return lEnd - lBegin + 1;
	}

	if (*(lhs + lBegin) == *(rhs + rBegin))
		return cacDistance(lhs, lBegin + 1, lEnd, rhs, rBegin + 1, rEnd);
	else
	{
		int t1 = cacDistance(lhs, lBegin + 1, lEnd, rhs, rBegin + 1, rEnd);
		int t2 = cacDistance(lhs, lBegin + 1, lEnd, rhs, rBegin, rEnd);
		int t3 = cacDistance(lhs, lBegin, lEnd, rhs, rBegin + 1, rEnd);
		return min(t1, min(t2, t3)) + 1;
	}
}

void main()
{
	const char *str1 = "kitten";
	const char *str2 = "sitting";
	int result = cacDistance(str1, 0, strlen(str1) - 1, str2, 0, strlen(str2) - 1);
	cout << "result: " << result << endl;
}

用动态规划来解此题,代码如下:

#include <iostream>

using namespace std;

int info[10][10];

void print(int size1, int size2)
{
	for (int i = 1; i <= size1; i++)
	{
		for (int j = 1; j <= size2; j++)
		{
			cout << info[i][j] << " ";
		}
		cout << endl;
	}
}

int cacDistance(const char *str1, const char *str2)
{
	if (str1 == NULL || str2 == NULL)
		return -1;

	int size1 = strlen(str1);
	int size2 = strlen(str2);
	for (int i = 0; i < size1; i++)
		info[i][size2] = 0;
	for (int j = 0; j < size2; j++)
		info[size1 - 1][j] = 0;

	for (int i = 1; i <= size1; i++)
	{
		for (int j = 1; j <= size2; j++)
		{
			if (str1[i - 1] == str2[j - 1])
				info[i][j] = info[i - 1][j - 1];
			else if (str1[i - 1] != str2[j - 1])
				info[i][j] = min(info[i - 1][j - 1], min(info[i - 1][j], info[i][j - 1])) + 1;
		}
	}

	print(size1, size2);
	return info[size1][size2];
}

void main()
{
	const char *str1 = "kitten";
	const char *str2 = "sitting";
	int result = cacDistance(str1, str2);
	cout << "result: " << result << endl;
}

递归的建表解法,也就是书上说的避免重复计算解法

#include <iostream>

using namespace std;

int info[10][10];
int INF = -1;

int cacDistance(const char *lhs, int lBegin, int lEnd,
				const char *rhs, int rBegin, int rEnd)
{
	if (lBegin == lEnd)
	{
		return info[lBegin + 1][rBegin + 1] + rEnd - rBegin;
	}
	else if (rBegin == rEnd)
	{
		return info[lBegin + 1][rBegin + 1] + lEnd - lBegin;
	}

	if (info[lBegin + 1][rBegin + 1] != -1)
	{
		return info[lBegin + 1][rBegin + 1];
	}

	if (*(lhs + lBegin) == *(rhs + rBegin))
		info[lBegin][rBegin] = cacDistance(lhs, lBegin + 1, lEnd, rhs, rBegin + 1, rEnd);
	else
	{
		int t1 = cacDistance(lhs, lBegin + 1, lEnd, rhs, rBegin + 1, rEnd);
		int t2 = cacDistance(lhs, lBegin + 1, lEnd, rhs, rBegin, rEnd);
		int t3 = cacDistance(lhs, lBegin, lEnd, rhs, rBegin + 1, rEnd);
		info[lBegin][rBegin] = min(t1, min(t2, t3)) + 1;
	}

	return info[lBegin][rBegin];
}

void main()
{
	const char *str1 = "kitten";
	const char *str2 = "sitting";
	int size1 = strlen(str1);
	int size2 = strlen(str2);
	for (int i = 0; i <= size1; i++)
		info[i][size2 - 1] = 0;
	for (int j = 0; j <= size2; j++)
		info[size1 - 1][j] = 0;

	for (int i = 1; i <= size1; i++)
	{
		for (int j = 1; j <= size2; j++)
		{
			info[i][j] = -1;
		}
	}
	int result = cacDistance(str1, 0, size1, str2, 0, size2);
	cout << "result: " << result << endl;
}


Nano-ESG数据资源库的构建基于2023年初至2024年秋季期间采集的逾84万条新闻文本,从中系统提炼出企业环境、社会及治理维度的信息。其构建流程首先依据特定术语在德语与英语新闻平台上检索,初步锁定与德国DAX 40成分股企业相关联的报道。随后借助嵌入技术对文本段落执行去重操作,以降低内容冗余。继而采用GLiNER这一跨语言零样本实体识别系统,排除与目标企业无关的文档。在此基础上,通过GPT-3.5与GPT-4o等大规模语言模型对文本进行双重筛选:一方面判定其与ESG议题的相关性,另一方面生成简明的内容概要。最终环节由GPT-4o模型完成,它对每篇文献进行ESG情感倾向(正面、中性或负面)的判定,并标注所涉及的ESG具体维度,从而形成具备时序特征的ESG情感与维度标注数据集。 该数据集适用于多类企业可持续性研究,例如ESG情感趋势分析、ESG维度细分类别研究,以及企业可持续性事件的时序演变追踪。研究者可利用数据集内提供的新闻摘要、情感标签与维度分类,深入考察企业在不同时期的环境、社会及治理表现。此外,借助Bertopic等主题建模方法,能够从数据中识别出与企业相关的核心ESG议题,并观察这些议题随时间的演进轨迹。该资源以其开放获取特性与连续的时间覆盖,为探究企业可持续性表现的动态变化提供了系统化的数据基础。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值