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