NER 实体识别 字符串(含汉字)解析 2021届 58笔试

NER 实体识别 字符串(含汉字)解析

问题描述(非完整版)

在这里插入图片描述

输入样例

time:月,time:日,loc:小区,loc:超市;5月1号在新龙城或浩客见;月 月 日 日 O 小区 小区 小区 O 超市 超市 O

解答

本题主要还是解析字符串,搞清楚汉字和英文等其他字符的存储方式不同,其实题目就简单了。

1. 判断一个字符是否为汉字的起始

汉字根据编码的不同,可能占个字节也可能是 个,这个可以通过strlen(“中”)计算出其大小;
然后,汉字的每个字节的最高位都是1,故:

/*
判断一个字符是否为汉字的起始
*/
bool is_zh_ch(char ch)
{
	/*
	汉字的两个字节的最高位都是1,所以判断第一个字节的最高位是0或1(是汉字)即可;
	*/
	return ch >> 8;
}
2. istringstream分离字符串
/*
根据分隔符分离字符串,默认空格为分隔符
返回该字符串按分隔符分割后的字符串数组
*/
vector<string> str_split(vector<string> &res, string input, char dilimiter = ' '){
	istringstream iss(input);
	string s;
	while (getline(iss, s, dilimiter)) {
		//cout << s << endl;
		res.push_back(s);
	}
	return res;
}
3. 句子分离
/*
将含有汉字、数字的句子,分离成一个汉字、连续数字为一个字符串
*/
vector<string> words_split(string &str, vector<string> &words) {
	string zh;
	int j, len = strlen("中");

	for (int i = 0; i < str.size(); ) {
		string tmp;
		if (is_zh_ch(str[i])) {
			j = 0;
			while (j < len) {
				tmp.push_back(str[i++]);
				j++;
			}
		}
		else {
			j = i;
			while (str[i] >= '0' && str[i] <= '9') {
				i++;
			}
			tmp = str.substr(j, i - j);
		}
		words.push_back(tmp);
	}
	return words;
}
4. 识别实体
/*
识别实体
*/
string NER(string strs[]) {
	string res, tmp;
	map<string, string> hash;
	vector<string> mapped, words, tags;
	for (auto str : str_split(mapped, strs[0], ',')) {/* mapping */
		vector<string> tmpstr;
		str_split(tmpstr, str, ':');
		hash[tmpstr[1]] = tmpstr[0];
	}
	words_split(strs[1], words);
	str_split(tags, strs[2]);

	/* recognize & print */
	//cout << hash[tags[0]] << ":";
	res.append(hash[tags[0]] + ":");
	for (int i = 0; i < tags.size(); i++) {
		if (hash.find(tags[i]) == hash.end()) {
			if (i == tags.size() - 1) {
				break;
			}
			tmp = "," + hash[tags[i+1]] + ":";
		}
		else {
			tmp = words[i];
		}
		//cout << tmp;
		res.append(tmp);
	}
	return res;
}
主函数读取输入信息
int main(void) {
	//while(1){
		string strs[3];

		getline(cin, strs[0], ';');/* 读取实体属性对应关系序列 */
		getline(cin, strs[1], ';');/* 用户原话 */
		getline(cin, strs[2]);/* 识别实体属性标签 */

		cout << NER(strs);
	//}
	//while (1);
	return 0;
}

完整源码

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <sstream>

using namespace std;

/*
判断一个字符是否为汉字的起始
*/
bool is_zh_ch(char ch){
	/*
	汉字的两个字节的最高位都是1,所以判断第一个字节的最高位是0或1(是汉字)即可;
	*/
	return ch >> 8;
}
/*
根据分隔符分离字符串,默认空格为分隔符
返回该字符串按分隔符分割后的字符串数组
*/
vector<string> str_split(vector<string> &res, string input, char dilimiter = ' '){
	istringstream iss(input);
	string s;
	while (getline(iss, s, dilimiter)) {
		//cout << s << endl;
		res.push_back(s);
	}
	return res;
}
/*
将含有汉字、数字的句子,分离成一个汉字、连续数字为一个字符串
*/
vector<string> words_split(string &str, vector<string> &words) {
	string zh;
	int j, len = strlen("中");

	for (int i = 0; i < str.size(); ) {
		string tmp;
		if (is_zh_ch(str[i])) {
			j = 0;
			while (j < len) {
				tmp.push_back(str[i++]);
				j++;
			}
		}
		else {
			j = i;
			while (str[i] >= '0' && str[i] <= '9') {
				i++;
			}
			tmp = str.substr(j, i - j);
		}
		words.push_back(tmp);
	}
	return words;
}
/*
识别实体
*/
string NER(string strs[]) {
	string res, tmp;
	map<string, string> hash;
	vector<string> mapped, words, tags;
	for (auto str : str_split(mapped, strs[0], ',')) {/* mapping */
		vector<string> tmpstr;
		str_split(tmpstr, str, ':');
		hash[tmpstr[1]] = tmpstr[0];
	}
	words_split(strs[1], words);
	str_split(tags, strs[2]);

	/* recognize & print */
	//cout << hash[tags[0]] << ":";
	res.append(hash[tags[0]] + ":");
	for (int i = 0; i < tags.size(); i++) {
		if (hash.find(tags[i]) == hash.end()) {
			if (i == tags.size() - 1) {
				break;
			}
			tmp = "," + hash[tags[i+1]] + ":";
		}
		else {
			tmp = words[i];
		}
		//cout << tmp;
		res.append(tmp);
	}
	return res;
}

int main(void) {
	while(1){
		string strs[3];

		getline(cin, strs[0], ';');/* 读取实体属性对应关系序列 */
		getline(cin, strs[1], ';');/* 用户原话 */
		getline(cin, strs[2]);/* 识别实体属性标签 */

		cout << NER(strs);
	}
	while (1);
	return 0;
}

2020/09/01 13:37
@luxurylu

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值