mirror of
https://github.com/yanyiwu/cppjieba.git
synced 2025-07-18 00:00:12 +08:00
增加两条词性标注的规则,针对连续英文和数字。
This commit is contained in:
parent
9d5359fc34
commit
e9cbec02c2
@ -5,6 +5,7 @@
|
||||
1. 修改两条更细粒度的特殊过滤规则,将连续的数字(包括浮点数)和连续的字母单独切分出来(而不会混在一起)。
|
||||
2. 修改最大概率法时动态规划过程需要使用的 DAG 数据结构(同时也修改 Trie 的 DAG 查询函数),提高分词速度 8% 。
|
||||
3. 使用了 `Aho-Corasick-Automation` 算法提速 Trie 查找的过程等优化,提升性能。
|
||||
4. 增加词性标注的两条特殊规则。
|
||||
|
||||
## v2.4.3
|
||||
|
||||
|
@ -9,7 +9,7 @@ CppJieba是"结巴"中文分词的C++版本
|
||||
## 特性
|
||||
|
||||
+ 源代码都写进头文件`src/*.hpp`里,`include`即可使用。
|
||||
+ 支持`utf-8, gbk`编码,但是推荐使用`utf-8`编码。
|
||||
+ 支持`utf-8, gbk`编码,但是推荐使用`utf-8`编码, 因为`gbk`编码缺少严格测试,慎用。
|
||||
+ 内置分词服务`server/server.cpp`,在linux环境下可安装使用。
|
||||
+ 项目自带较为完善的单元测试,核心功能中文分词(utf8)的稳定性接受过线上环境检验。
|
||||
+ 支持载自定义用户词典。
|
||||
@ -268,7 +268,7 @@ make && ./keyword.demo
|
||||
详情请看 `test/tagging_demo.cpp`.
|
||||
|
||||
```
|
||||
["我:r", "是:v", "蓝翔:x", "技工:n", "拖拉机:n", "学院:n", "手扶拖拉机:n", "专业:n", "的:uj", "。:x", "不用:v", "多久:m", ",:x", "我:r", "就:d", "会:v", "升职:v", "加薪:nr", ",:x", "当:t", "上:f", "总经理:n", ",:x", "出任:v", "CEO:x", ",:x", "迎娶:v", "白富美:x", ",:x", "走上:v", "人生:n", "巅峰:n", "。:x"]
|
||||
["我:r", "是:v", "蓝翔:x", "技工:n", "拖拉机:n", "学院:n", "手扶拖拉机:n", "专业:n", "的:uj", "。:x", "不用:v", "多久:m", ",:x", "我:r", "就:d", "会:v", "升职:v", "加薪:nr", ",:x", "当:t", "上:f", "总经理:n", ",:x", "出任:v", "CEO:eng", ",:x", "迎娶:v", "白富美:x", ",:x", "走上:v", "人生:n", "巅峰:n", "。:x"]
|
||||
```
|
||||
|
||||
支持自定义词性。
|
||||
@ -281,10 +281,10 @@ make && ./keyword.demo
|
||||
结果如下:
|
||||
|
||||
```
|
||||
["我:r", "是:v", "蓝翔:nz", "技工:n", "拖拉机:n", "学院:n", "手扶拖拉机:n", "专业:n", "的:uj", "。:x", "不用:v", "多久:m", ",:x", "我:r", "就:d", "会:v", "升职:v", "加薪:nr", ",:x", "当:t", "上:f", "总经理:n", ",:x", "出任:v", "CEO:x", ",:x", "迎娶:v", "白富美:x", ",:x", "走上:v", "人生:n", "巅峰:n", "。:x"]
|
||||
["我:r", "是:v", "蓝翔:nz", "技工:n", "拖拉机:n", "学院:n", "手扶拖拉机:n", "专业:n", "的:uj", "。:x", "不用:v", "多久:m", ",:x", "我:r", "就:d", "会:v", "升职:v", "加薪:nr", ",:x", "当:t", "上:f", "总经理:n", ",:x", "出任:v", "CEO:eng", ",:x", "迎娶:v", "白富美:x", ",:x", "走上:v", "人生:n", "巅峰:n", "。:x"]
|
||||
```
|
||||
|
||||
## 词典资料
|
||||
## 其它词典资料分享
|
||||
|
||||
+ [dict.367W.utf8.tar.gz] iLife(`562193561@qq.com`)
|
||||
|
||||
|
@ -21,7 +21,7 @@ namespace CppJieba
|
||||
const double MIN_DOUBLE = -3.14e+100;
|
||||
const double MAX_DOUBLE = 3.14e+100;
|
||||
const size_t DICT_COLUMN_NUM = 3;
|
||||
const char* const UNKNOWN_TAG = "x";
|
||||
const char* const UNKNOWN_TAG = "";
|
||||
|
||||
class DictTrie
|
||||
{
|
||||
|
@ -9,6 +9,10 @@ namespace CppJieba
|
||||
{
|
||||
using namespace Limonp;
|
||||
|
||||
static const char* const POS_M = "m";
|
||||
static const char* const POS_ENG = "eng";
|
||||
static const char* const POS_X = "x";
|
||||
|
||||
class PosTagger
|
||||
{
|
||||
private:
|
||||
@ -39,6 +43,7 @@ namespace CppJieba
|
||||
LIMONP_CHECK(_dictTrie);
|
||||
};
|
||||
|
||||
|
||||
bool tag(const string& src, vector<pair<string, string> >& res) const
|
||||
{
|
||||
vector<string> cutRes;
|
||||
@ -58,11 +63,46 @@ namespace CppJieba
|
||||
return false;
|
||||
}
|
||||
tmp = _dictTrie->find(unico.begin(), unico.end());
|
||||
res.push_back(make_pair(*itr, tmp == NULL ? "x" : tmp->tag));
|
||||
if(tmp == NULL || tmp->tag.empty())
|
||||
{
|
||||
res.push_back(make_pair(*itr, _specialRule(unico)));
|
||||
}
|
||||
else
|
||||
{
|
||||
res.push_back(make_pair(*itr, tmp->tag));
|
||||
}
|
||||
}
|
||||
tmp = NULL;
|
||||
return !res.empty();
|
||||
}
|
||||
private:
|
||||
const char* _specialRule(const Unicode& unicode) const
|
||||
{
|
||||
size_t m = 0;
|
||||
size_t eng = 0;
|
||||
for(size_t i = 0; i < unicode.size() && eng < unicode.size() / 2; i++)
|
||||
{
|
||||
if(unicode[i] < 0x80)
|
||||
{
|
||||
eng ++;
|
||||
if('0' <= unicode[i] && unicode[i] <= '9')
|
||||
{
|
||||
m++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ascii char is not found
|
||||
if(eng == 0)
|
||||
{
|
||||
return POS_X;
|
||||
}
|
||||
// all the ascii is number char
|
||||
if(m == eng)
|
||||
{
|
||||
return POS_M;
|
||||
}
|
||||
// the ascii chars contain english letter
|
||||
return POS_ENG;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,24 @@ namespace CppJieba
|
||||
{
|
||||
return encode(uni.begin(), uni.end(), res);
|
||||
}
|
||||
|
||||
// compiler is expected to optimized this function to avoid return value copy
|
||||
inline string encode(Unicode::const_iterator begin, Unicode::const_iterator end)
|
||||
{
|
||||
string res;
|
||||
res.reserve(end - begin);
|
||||
encode(begin, end, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
// compiler is expected to optimized this function to avoid return value copy
|
||||
inline Unicode decode(const string& str)
|
||||
{
|
||||
Unicode unicode;
|
||||
unicode.reserve(str.size());
|
||||
decode(str, unicode);
|
||||
return unicode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
2
test/testdata/userdict.utf8
vendored
2
test/testdata/userdict.utf8
vendored
@ -2,3 +2,5 @@
|
||||
韩玉鉴赏
|
||||
A
|
||||
B
|
||||
iphone6
|
||||
蓝翔 nz
|
||||
|
@ -3,26 +3,41 @@
|
||||
|
||||
using namespace CppJieba;
|
||||
|
||||
const char * const QUERY_TEST1 = "我是蓝翔技工拖拉机学院手扶拖拉机专业的。不用多久,我就会升职加薪,当上总经理,出任CEO,迎娶白富美,走上人生巅峰。";
|
||||
const char * const ANS_TEST1 = "[\"我:r\", \"是:v\", \"蓝翔:x\", \"技工:n\", \"拖拉机:n\", \"学院:n\", \"手扶拖拉机:n\", \"专业:n\", \"的:uj\", \"。:x\", \"不用:v\", \"多久:m\", \",:x\", \"我:r\", \"就:d\", \"会:v\", \"升职:v\", \"加薪:nr\", \",:x\", \"当上:t\", \"总经理:n\", \",:x\", \"出任:v\", \"CEO:x\", \",:x\", \"迎娶:v\", \"白富:x\", \"美:ns\", \",:x\", \"走上:v\", \"人生:n\", \"巅峰:n\", \"。:x\"]";
|
||||
const char * const QUERY_TEST2 = "我是蓝翔技工拖拉机学院手扶拖拉机专业的。不用多久,我就会升职加薪,当上总经理,出任CEO,迎娶白富美,走上人生巅峰。";
|
||||
const char * const ANS_TEST2 = "[\"我:r\", \"是:v\", \"蓝翔:nz\", \"技工:n\", \"拖拉机:n\", \"学院:n\", \"手扶拖拉机:n\", \"专业:n\", \"的:uj\", \"。:x\", \"不用:v\", \"多久:m\", \",:x\", \"我:r\", \"就:d\", \"会:v\", \"升职:v\", \"加薪:nr\", \",:x\", \"当上:t\", \"总经理:n\", \",:x\", \"出任:v\", \"CEO:x\", \",:x\", \"迎娶:v\", \"白富:x\", \"美:ns\", \",:x\", \"走上:v\", \"人生:n\", \"巅峰:n\", \"。:x\"]";
|
||||
static const char * const QUERY_TEST1 = "我是蓝翔技工拖拉机学院手扶拖拉机专业的。不用多久,我就会升职加薪,当上总经理,出任CEO,迎娶白富美,走上人生巅峰。";
|
||||
static const char * const ANS_TEST1 = "[\"我:r\", \"是:v\", \"蓝翔:x\", \"技工:n\", \"拖拉机:n\", \"学院:n\", \"手扶拖拉机:n\", \"专业:n\", \"的:uj\", \"。:x\", \"不用:v\", \"多久:m\", \",:x\", \"我:r\", \"就:d\", \"会:v\", \"升职:v\", \"加薪:nr\", \",:x\", \"当上:t\", \"总经理:n\", \",:x\", \"出任:v\", \"CEO:eng\", \",:x\", \"迎娶:v\", \"白富:x\", \"美:ns\", \",:x\", \"走上:v\", \"人生:n\", \"巅峰:n\", \"。:x\"]";
|
||||
static const char * const QUERY_TEST2 = "我是蓝翔技工拖拉机学院手扶拖拉机专业的。不用多久,我就会升职加薪,当上总经理,出任CEO,迎娶白富美,走上人生巅峰。";
|
||||
static const char * const ANS_TEST2 = "[\"我:r\", \"是:v\", \"蓝翔:nz\", \"技工:n\", \"拖拉机:n\", \"学院:n\", \"手扶拖拉机:n\", \"专业:n\", \"的:uj\", \"。:x\", \"不用:v\", \"多久:m\", \",:x\", \"我:r\", \"就:d\", \"会:v\", \"升职:v\", \"加薪:nr\", \",:x\", \"当上:t\", \"总经理:n\", \",:x\", \"出任:v\", \"CEO:eng\", \",:x\", \"迎娶:v\", \"白富:x\", \"美:ns\", \",:x\", \"走上:v\", \"人生:n\", \"巅峰:n\", \"。:x\"]";
|
||||
|
||||
TEST(PosTaggerTest, Test1)
|
||||
static const char * const QUERY_TEST3 = "iphone6手机的最大特点是很容易弯曲。";
|
||||
static const char * const ANS_TEST3 = "[\"iphone6:eng\", \"手机:n\", \"的:uj\", \"最大:a\", \"特点:n\", \"是:v\", \"很:zg\", \"容易:a\", \"弯曲:v\", \"。:x\"]";
|
||||
//static const char * const ANS_TEST3 = "";
|
||||
|
||||
TEST(PosTaggerTest, Test)
|
||||
{
|
||||
PosTagger tagger("../dict/jieba.dict.utf8", "../dict/hmm_model.utf8");
|
||||
vector<pair<string, string> > res;
|
||||
tagger.tag(QUERY_TEST1, res);
|
||||
string s;
|
||||
s << res;
|
||||
ASSERT_TRUE(s == ANS_TEST1);
|
||||
{
|
||||
vector<pair<string, string> > res;
|
||||
tagger.tag(QUERY_TEST1, res);
|
||||
string s;
|
||||
s << res;
|
||||
ASSERT_TRUE(s == ANS_TEST1);
|
||||
}
|
||||
}
|
||||
TEST(PosTaggerTest, Test2)
|
||||
TEST(PosTagger, TestUserDict)
|
||||
{
|
||||
PosTagger tagger("../dict/jieba.dict.utf8", "../dict/hmm_model.utf8", "../dict/user.dict.utf8");
|
||||
vector<pair<string, string> > res;
|
||||
tagger.tag(QUERY_TEST2, res);
|
||||
string s;
|
||||
s << res;
|
||||
ASSERT_TRUE(s == ANS_TEST2);
|
||||
PosTagger tagger("../dict/jieba.dict.utf8", "../dict/hmm_model.utf8", "../test/testdata/userdict.utf8");
|
||||
{
|
||||
vector<pair<string, string> > res;
|
||||
tagger.tag(QUERY_TEST2, res);
|
||||
string s;
|
||||
s << res;
|
||||
ASSERT_EQ(s, ANS_TEST2);
|
||||
}
|
||||
{
|
||||
vector<pair<string, string> > res;
|
||||
tagger.tag(QUERY_TEST3, res);
|
||||
string s;
|
||||
s << res;
|
||||
ASSERT_EQ(s, ANS_TEST3);
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ TEST(DictTrieTest, UserDict)
|
||||
ASSERT_TRUE(unit);
|
||||
string res ;
|
||||
res << *unit;
|
||||
ASSERT_EQ("[\"20113\", \"35745\", \"31639\"] x -2.975", res);
|
||||
ASSERT_EQ("[\"20113\", \"35745\", \"31639\"] -2.975", res);
|
||||
}
|
||||
|
||||
TEST(DictTrieTest, automation)
|
||||
|
Loading…
x
Reference in New Issue
Block a user