字符相似度计算

1. 问题描述

在做自然语言处理的时候,我们有可能会搭建到语音转换文字的模型。为了训练这个模型,我们需要设计一个相似度模型用于匹配目标输出和模型输出的相似度。
Input
输入两行,每行一个句子,第一行是目标输出,第二行是模型输出。
Output
输出它们的相似度,保留两位小数。
相似度=目标输出和模型输出单词元素的交集的元素个数 / 目标输出和模型输出单词元素的并集的元素个数。
样例

Input:
I am a college student
I am an college students

Output:
0.43

2. 思路

题目说得很清楚了,就是求集合的交集和并集。但是,处理输入的数据有一点难点:没有告诉每行的单词数,一行的输入以换行结束,所以怎么把两个句子里的单词分开存有点难。C++没有像Python中的split那样的神器,要把句子中的单词分割出来可以用find()定位出空格字符的位置,再用substr()截出来,不过这样有点麻烦,这里用stringstream来解决。先看个例子:

#include <iostream>
#include <sstream>

using namespace std;

int main()
{
	string s;
	stringstream ss;
	getline(cin, s);	// 输入以回车结束,可以输入空格
	ss << s;			// 将s输出到ss对象中
	string st;
	while(ss >> st) {	// 一个单词一个单词输出
		cout << st << endl;
	}
	return 0;
}

Input:
I am a college student

output:
I
am
a
college
student

3. 参考代码

#include <stdio.h>
#include <iostream>
#include <sstream>
#include <string>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;

/*统一输入*/
void input(set<string>& st)
{
	string line;
	getline(cin, line);
	stringstream ss;
	ss << line;
	string temp;
	// 将句子中的单词放到set中
	while (ss >> temp) st.insert(temp);
}

int main()
{
	set<string> a;
	set<string> b;

	input(a);				// 第一行输入
	input(b);				// 第二行输入

	vector<string> res_i;	// 交集结果
	vector<string> res_u;	// 并集结果


	set_intersection(a.begin(), a.end(), b.begin(), b.end(), back_inserter(res_i));
	set_union(a.begin(), a.end(), b.begin(), b.end(), back_inserter(res_u));

#define NDEBUG
#ifndef NDEBUG
	cout << "intersection number=" << res_i.size() << "\t"
		<< "union number=" << res_u.size() << endl;
#endif

	printf("%.2f", res_i.size()*1.0 / res_u.size());

	return 0;
}

4. 笔记

求交集set_intersection()和求并集set_union()函数:在上面代码中,两个set对象的处理结果最后放在了vector中,为什么不用set来存放结果呢?

set<string> res_ii;	// 用set对象来存放结果
set_intersection(a.begin(), a.end(), b.begin(), b.end(), back_inserter(res_ii));

运行一下,报错了:大意是说set类没有push_back()操作。那就定义一个自己的MySet实现一下:

template <class Ty>
class MySet :public set<Ty>
{
public:
	// 继承set类,添加一个push_back函数并实现
	inline void push_back(const Ty& _Val) {
		this->insert(_Val);
	}
}

使用自己定义的MySet类就可以使用set来存放结果了:

MySet<string> mst;	// 用自己定义的MySet对象来存放结果
set_intersection(a.begin(), a.end(), b.begin(), b.end(), back_inserter(mst));

*补充:*发现一个插入迭代器insert_iterator可以用,C++文档这么写的:

The container needs to have an insert member function (such as most standard containers).

所以求交集和并集可以这样用:

// 要加上头文件#include <iterator>
#include <iterator>
...
set<string> res_st;
set_intersection(a.begin(), a.end(), b.begin(), b.end(), insert_iterator<set<string>>(res_st,res_st.begin()));
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值