基于字的文本相似度算法——余弦定理

来源:互联网 发布:ps软件基础教程 编辑:程序博客网 时间:2024/06/05 07:43

一、算法原理

  基于字的文本相似度余弦定理算法的原理是:

(1)分别统计两个比较文本中所有字出现的频率,从而得出两个文本对应的向量
(2)利用余弦定理计算这两个向量的夹角余弦值

(3)根据自设置的阈值判断两个文本是否相似


二、算法的C++实现

这里引用的StringUtil.hpp文件引自:

https://github.com/yanyiwu/cppjieba/blob/master/deps/limonp/StringUtil.hpp


/* * CosineSimilarity.hpp * *  Created: 2016年10月2日 *   Author: tang */#ifndef SRC_COSINE_SIMILARITY_HPP_#define SRC_COSINE_SIMILARITY_HPP_#include <iostream>#include <vector>#include <map>#include <math.h>#include "StringUtil.hpp"using namespace std;class CosineSimilarity{public:CosineSimilarity(){}double CalculateTextSimilarity(string &str1,string &str2){vector<uint16_t> words_for_str1;vector<uint16_t> words_for_str2;vector<uint16_t>::iterator it;if(!utf8ToUnicode< vector<uint16_t> >(str1,words_for_str1) || !utf8ToUnicode< vector<uint16_t> >(str2,words_for_str2 ) ){cout<<"TransCode Error"<<endl;return 0.;}map< uint16_t,pair<int,int> >seq_map;map< uint16_t,pair<int,int> >::iterator map_it;for(it=words_for_str1.begin();it!=words_for_str1.end();++it){if(isHanzi(*it)){map_it=seq_map.find(*it);if(map_it!=seq_map.end()){map_it->second.first++;}else{pair<int,int> seq;seq.first=1;seq.second=0;seq_map[*it]=seq;}}}for(it=words_for_str2.begin();it!=words_for_str2.end();++it)                {if(isHanzi(*it))                        {                                map_it=seq_map.find(*it);                                        if(map_it!=seq_map.end())                                {                                        map_it->second.second++;                                }                                else                                {pair<int,int> seq;                                        seq.first=0;                                        seq.second=1;                                        seq_map[*it]=seq;                                }                        }                }double sqdoc1 = 0.;                 double sqdoc2 = 0.;                 double denominator = 0.;for(map_it=seq_map.begin();map_it!=seq_map.end();++map_it){pair<int,int> c=map_it->second;denominator +=(c.first * c.second);sqdoc1+=(c.first * c.first);sqdoc2+=(c.second * c.second);} if(0==sqdoc1 * sqdoc2)return -1.0;return denominator/sqrt(sqdoc1 * sqdoc2);}bool codeFilter(int code) {        if ((code < 0x4e00 || code > 0x9fa5) && !(code >= '0' && code <= '9') && !(code >= 'a' && code <= 'z') && !(code >= 'A' && code <= 'Z'))            return false;                return true;}bool isHanzi(uint16_t ch){return (ch >= 0x4E00 && ch <= 0x9FA5);}};

三、算法的Java实现

import java.io.UnsupportedEncodingException;  import java.util.Date;  import java.util.HashMap;  import java.util.Iterator;  import java.util.Map; public class CosineSimilarity{    /** * 输入两段文本利用孜频率的余弦定理判断二者间的相似度 *  * @param doc1,文本1 * @param doc2,文本2 * @return 相似度值 */    public double CalculateTextSim(String doc1, String doc2) {if (doc1 != null && doc1.trim().length() > 0 && doc2 != null&& doc2.trim().length() > 0) {Map<Integer, int[]> AlgorithmMap = new HashMap<Integer, int[]>();//将两个字符串中的中文字符以及出现的总数封装到,AlgorithmMap中for (int i = 0; i < doc1.length(); i++) {char d1 = doc1.charAt(i);if(isHanZi(d1)){int charIndex = getGB2312Id(d1);if(charIndex != -1){int[] fq = AlgorithmMap.get(charIndex);if(fq != null && fq.length == 2){fq[0]++;}else {fq = new int[2];fq[0] = 1;fq[1] = 0;AlgorithmMap.put(charIndex, fq);}}}}for (int i = 0; i < doc2.length(); i++) {char d2 = doc2.charAt(i);if(isHanZi(d2)){int charIndex = getGB2312Id(d2);if(charIndex != -1){int[] fq = AlgorithmMap.get(charIndex);if(fq != null && fq.length == 2){fq[1]++;}else {fq = new int[2];fq[0] = 0;fq[1] = 1;AlgorithmMap.put(charIndex, fq);}}}}Iterator<Integer> iterator = AlgorithmMap.keySet().iterator();double sqdoc1 = 0;double sqdoc2 = 0;double denominator = 0; while(iterator.hasNext()){int[] c = AlgorithmMap.get(iterator.next());denominator += c[0]*c[1];sqdoc1 += c[0]*c[0];sqdoc2 += c[1]*c[1];}return denominator / Math.sqrt(sqdoc1*sqdoc2);} else {throw new NullPointerException("the Document is null or have not cahrs!!");}    }/** * 输入一个字符判断是否为中文汉字 *  * @param ch,字符 * @return true为中文汉字,否则为false */    public boolean isHanZi(char ch) {return (ch >= 0x4E00 && ch <= 0x9FA5);        }/** * 根据输入的Unicode字符,获取它的GB2312编码或者ascii编码, *  * @param ch,输入的GB2312中文字符或者ASCII字符(128个) * @return ch在GB2312中的位置,-1表示该字符不认识 */public static short getGB2312Id(char ch) {try {byte[] buffer = Character.toString(ch).getBytes("GB2312");if (buffer.length != 2) {// 正常情况下buffer应该是两个字节,否则说明ch不属于GB2312编码,故返回'?',此时说明不认识该字符return -1;}int b0 = (int) (buffer[0] & 0x0FF) - 161; // 编码从A1开始,因此减去0xA1=161int b1 = (int) (buffer[1] & 0x0FF) - 161; // 第一个字符和最后一个字符没有汉字,因此每个区只收16*6-2=94个汉字return (short) (b0 * 94 + b1);} catch (UnsupportedEncodingException e) {e.printStackTrace();}return -1;}}


1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 把人偷小孩的人贩子打死了怎么办 怀孕3个月没有胎心怎么办 社保局打印关系转移信封之后怎么办 长裙变装外出被发现了怎么办 超变陀螺怎么绳子拉不出来怎么办 梦幻诛仙传说时间得不到东西怎么办 夹在强势母亲和强势老公中间怎么办 工作调动校长总拖着不盖章怎么办 宝贝在妈妈肚子里发育慢怎么办 领导安排你负责一次讲座你怎么办 雷蛇北海巨妖耳机有回音怎么办 手机直播声卡有杂音有回音怎么办 大班见到陌生人入园怎么办安全教案 两首歌合并到一起中间有停顿怎么办 想做主持人但不是播音专业怎么办 动脉造影术2天后穿刺点出血怎么办 战舰世界买了重复金币船怎么办 戒指戴在手上取不下来怎么办 工作中难以和同事上司相处怎么办 老是被上司和同事欺负我该怎么办 桌面太低座位太高写字不舒服怎么办 一个人如果欠下网贷无法偿还怎么办 c语言的编译和运行不见了怎么办 8k纸的国庆节手抄报怎么办 合同员工签字了老板一直未签怎么办 下体长毛了很多肉芽很痒怎么办 对方拟把假离婚协议弄假成真怎么办 领主之塔改版后旧材料怎么办 汽车遥控钥匙打不开车门怎么办 苹果手机访问限制密码忘了怎么办 苹果的访问限制密码忘了怎么办 手机下雨天进水声音出了问题怎么办 胸太小了该怎么办经常揉胸会变大吗 鼻冲洗器冲鼻子耳朵进水怎么办 手表进水了然后里面有水珠怎么办 玩游戏后头晕恶心想吐怎么办 吃完美林3小时后又发烧怎么办 颜值和身材都是负分怎么办 妈妈离婚又有一个孩子我该怎么办 孩子妈妈天天给孩子吃药我该怎么办 被像蚂蚁有翅膀的虫子咬了怎么办