中文分词中用到的RMM(逆向最大匹配算法)算法。不说那么多了,我不是研究算法的,总之RMM这种基于词典的分词算法,准确率比较高就是了。我实现的这个方法,会把非词典的内容,全部拆分成单字。写了很多年了,忘记了很多,直接贴代码:
#include <map>
#include <vector>
#include <list>
#include <string>
#include <algorithm>
#include "tools.h"
using namespace std;
#ifndef PARTH
#define PARTH
#define _ARRAY_COUNT_(x) sizeof(x)/sizeof(*x)
#define _WPRINTF_(c) setlocale(LC_ALL,"chs"); wprintf( c ); cout << endl;
#define _WVECTOR_ vector<wstring>
void CreateVectorForArray(const wstring *arr, const int arr_len, vector<wstring> &vec);
void StrReplace(wstring &str, const wstring find, const wstring replace);
#define _WCreateVectorForArray_(src,target) CreateVectorForArray(src,_ARRAY_COUNT_(src),target);
#define _WInVectory(str, vec) WInVectory(str,vec)

void CreateVectorForArray(const wstring *arr, const int arr_len, vector<wstring> &vec){
vector<wstring> _tmp( arr, arr+arr_len );
vec.resize(arr_len);
copy(_tmp.begin(), _tmp.end(), vec.begin());
}
void StrReplace(wstring &str, const wstring find, const wstring replace){
string::size_type pos = 0;
while ( (pos = str.find(find, pos)) != wstring::npos ) {
str.replace( pos, find.size(), replace );
pos++;
}
}

typedef struct WordPartResultItem{
int count;
int startOffset;
int endOffset;
int sort;
float scale;
WordPartResultItem():count(0),startOffset(0),endOffset(0),scale(0),sort(0){};
} _WordPartResultItem;
typedef WordPartResultItem _WordPartResult;
class WordPart{
public:
WordPart( wstring word[], int word_len);
void SetContent( wstring content);
//分词时是否允许将每个单字分割词
bool is_single;
//执行分词
map<wstring,_WordPartResult> Part(); 
private:
//用于分词的词典
map<int,list<wstring>> words;
//词典总数
int words_length;
//将要分词的内容
wstring content;
//最大匹配词的长度
int max_length;
//忽略的字符
_WVECTOR_ trim_str;
//断句符号
_WVECTOR_ end_dot;
//获取最大匹配词的长度
int GetMaxLength(wstring *words);
void setResult( map<wstring,_WordPartResult> &result, int &sort, const wstring k, const int offset );
};
#endif;

WordPart::WordPart( wstring word[], int word_len){
//this->words = word;
this->words_length = word_len;
this->is_single = false;
max_length = GetMaxLength(word);
wstring trim_tmp[] = {L"\"",L"'",L"‘",L"’",L"“",L"”",L"\\",L"(",L")",L"(",L")"};
wstring end_tmp[] = {L".",L",",L"。",L",",L":",L":",L" "};
_WCreateVectorForArray_(trim_tmp,trim_str)
_WCreateVectorForArray_(end_tmp,end_dot)
//整理词典
for( int i=0; i<word_len; i++){
int k = word[i].size();
if( words.find(k) == words.end() ){
list<wstring> v;
words.insert( map<int,list<wstring>>::value_type(k,v) );
}
words[k].push_back(word[i]);
}
}
void WordPart::SetContent( wstring content){
_WVECTOR_::iterator iter;
for( iter=trim_str.begin(); iter!=trim_str.end(); iter++){
StrReplace(content,*iter,L" ");
}
this->content = content;
}
int WordPart::GetMaxLength(wstring *words){
int size = 0;
for( int i=0; i<words_length; i++ ){
if( words[i].length() > size )
size = words[i].length();
}
return size;
}
map<wstring,_WordPartResult> WordPart::Part(){
map<wstring,_WordPartResult> result;
if( content.empty() || words_length == 0 )
return result;
//如果要求切分单字
if( is_single ){
wstring cstr;
wstring eng;
int sort = 0;
for( int i=0; i<content.size(); i++ ){
cstr = content.substr(i,1);
if( (cstr < L"a" || cstr > L"z") && (cstr < L"A" || cstr > L"Z") && (cstr < L"0" || cstr > L"9") ){
if(!eng.empty()){
if( words.find(eng.size()) == words.end() 
|| find( words[eng.size()].begin(), words[eng.size()].end(), eng ) == words[eng.size()].end() )
setResult(result,sort,eng,i-eng.size());
eng.clear();
}
if( words.find(1) == words.end() 
|| find( words[1].begin(), words[1].end(), cstr ) == words[1].end() )
setResult(result,sort,cstr,i);
}else{
eng.append(cstr);
}
}
if(!eng.empty()){
if( words.find(eng.size()) == words.end() 
|| find( words[eng.size()].begin(), words[eng.size()].end(), eng ) == words[eng.size()].end() )
setResult(result,sort,eng,content.size()-eng.size());
eng.clear();
}
}
_WVECTOR_ line;
wstring one_line = L"";
//段句
for( int i=0; i<content.size(); i++ ){
wstring str = content.substr( i, 1 );
if( find(end_dot.begin(),end_dot.end(),str) == end_dot.end() ){
one_line.append(str);
}else{
line.insert(line.begin(),one_line);
one_line.clear();
}
if( i==content.size() - 1 && !one_line.empty() ){
line.insert(line.begin(),one_line);
}
}
int content_size = content.size(), offset = content_size, sort = 0;
for(_WVECTOR_::iterator i=line.begin(); i != line.end(); i++){
offset -= (*(i)).size();
if( i != line.begin() ){
offset -= 1; //断句符号位置
}
//分词
wstring str = *i; //段内容
wstring cstr; //分段内容
int begin = 0,pointer; //游标,一个全局游标,和一个相对游标
int k; //词典键
int sublength = max_length; //每个查询字符的长度
if( str.size() > max_length ){
begin = str.size() - max_length;
}else{
sublength = str.size();
}
while (begin != -sublength)
{
pointer = 0;
while( pointer < sublength ){
if( begin >= 0 ){
cstr = str.substr( begin, sublength-pointer );
k = cstr.size();
if( words.find(k) != words.end() && find(words[k].begin(),words[k].end(),cstr)!=words[k].end() ){
setResult(result,sort,cstr,offset+begin);
break;
}
}
pointer++;
if( pointer < sublength )
begin++;
}
begin-=sublength;
}
}
return result;
}
void WordPart::setResult( map<wstring,_WordPartResult> &result, int &sort, const wstring k, const int offset ){
if( result.find(k) == result.end() ){
_WordPartResultItem row;
result.insert( map<wstring,_WordPartResult>::value_type(k,row) );
result[k].startOffset = offset;
result[k].sort = sort;
sort++;
}
result[k].count += 1;
result[k].endOffset = offset;

}

以前用C++实现的RMM分词类型相关推荐

  1. 北京大学开源分词工具pkuseg 初试与使用感受

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/meiqi0538/article/de ...

  2. jiebaR中文分词,从入门到喜欢

    之前,我写过一篇关于Rwordseg包的分词,链接为:http://blog.csdn.net/wzgl__wh/article/details/52528925 今天,我主要想谈谈自己对jiebaR ...

  3. solr配置同义词,停止词,和扩展词库(IK分词器为例)

    定义 同义词:搜索结果里出现的同义词.如我们输入"还行",得到的结果包括同义词"还可以". 停止词:在搜索时不用出现在结果里的词.比如is .a .are .& ...

  4. elasticsearch-7.15.2 同时支持中文ik分词器和pinyin分词器

    文章目录 1. 自定义分词器 2. 映射模型 3. 效果图 1. 自定义分词器 ES如何支持拼音和中文分词 ? 自定义分词器 支持拼音和中文分词 PUT /jd_goods {"settin ...

  5. solr mysql 分词_solr学习篇(二) solr 分词器篇

    关于solr7.4搭建与配置可以参考 solr7.4 安装配置篇  在这里我们探讨一下分词的配置 目录 1.关于分词 1.分词是指将一个中文词语拆成若干个词,提供搜索引擎进行查找,比如说:北京大学 是 ...

  6. 用 StarRocks on ES 实现 分词

    目录 部署ES 下载 Config 系统参数 启动 Verify 常规用法 创建Index _cat 查看settings 删除index Bulk导入数据 Search SR 外表 测试1:分词 E ...

  7. Elasticsearch配置拼音分词和自定义分词器

    下载elasticsearch-analysis-pinyin拼音分词器  https://codeload.github.com/medcl/elasticsearch-analysis-pinyi ...

  8. NLP 中文分词-双向匹配算法(理论+Python实现)

    一.理论描述 1.中文分词的概念: 是指把没有明显分界标志的字串切分为词串,包括标点符号.数字.数学符号.各种标记.人名.地名.机构名等未登录词的识别.汉语自动分词主要包括:(1)根据分词规范,建立机 ...

  9. MM、RMM、Bi_MM

    写在前面的话 本文参考<Python自然语言处理实战 核心技术与算法>,一本不可多得的自然语言处理入门书籍. MM.RMM.Bi_MM都是基于规则分词的算法,通过匹配所持有的字典,进行分词 ...

最新文章

  1. sql 基础--mysql 5 (6)
  2. 使用OpenCV校准鱼眼镜头-第2部分
  3. MPLS LDP随堂笔记1
  4. 武汉理工java_Java语言程序设计E
  5. centos7安装Oracle12(完整版)
  6. qtdesigner 组件全吗_百度营销工具有哪些?带你了解百度全链路营销
  7. 【Android RTMP】音频数据采集编码 ( FAAC 编码器编码 AAC 音频解码信息 | 封装 RTMP 音频数据头 | 设置 AAC 音频数据类型 | 封装 RTMP 数据包 )
  8. Java多线程设计模式(1)
  9. java opengl_java基于OpenGL ES实现渲染实例
  10. ppt格式刷快捷键_普通人 | 4个我在知乎上都没有见过的PPT实用技巧
  11. [实践系列]Promises/A+规范
  12. Angstrom移植操作
  13. access重复数据累计_小程序·云开发之数据库自动备份丨云开发101
  14. C++——override
  15. MongoDB vs MySQL,哪个效率更高?
  16. 介绍KMP算法思想(例题:ACWING 831 kmp字符串)
  17. C++中rapidxml用法及例子
  18. Android平台快速集成当下流行平台分享
  19. JMeter(二十一):使用BeanShell解析Json格式的报文
  20. 易语言人脸识别算法源码

热门文章

  1. 树状数组及线段树入门(SDNU1665-1668)
  2. 客户订单管理系统使用教程
  3. vs2015c语言内嵌汇编,C#中内嵌资源的读取
  4. conda search cuda后没有版本10的问题
  5. 天津达内可靠么 老员工揭秘真实的达内教育
  6. 微信为什么打不开html,微信为什么打不开?解决微信打不开图文教程
  7. 老毛桃 安装linux双系统,安装CentOS 7双系统(二)——安装过程step by step
  8. 原生JS 和 jQuery 通过url传递 和 接收 自定义参数
  9. (Tiled官方文档翻译)第一节:简介及创建工程、图层集
  10. 图像类的分类模型假阳性(FP)高的解决思路