字符串关联度求解算法改进模型
来源:互联网 发布:施工软件哪个好 编辑:程序博客网 时间:2024/06/08 11:25
注意要把string类型的词转成unicode32的,这样计算的长度就是字符的长度
数据整理
如果文本中有英文,如“abc”,把”abc”看成一个词来计算,返回一个vector<vector<int>>
类型的词
vector<vector<int>> getRealWord(vector<int> result) { vector<vector<int>> realWord; vector<int> temp; for (auto it = result.begin(); it != result.end(); ++it) { //判断是否英文或数字 if ((*(it) > u'\u0061' && *(it) < u'\u007a') || (*(it) > u'\u0041' && *(it) < u'\u005a') || (*(it) >= u'\u0030' && *(it) <= u'\u0039')) { temp.push_back(*it); } else { if (!temp.empty()) { realWord.push_back(temp); //清空一下,只记录一个单词 temp.clear(); } temp.push_back(*it); } } realWord.push_back(temp); return realWord;}
UTF8转UTF32
#include "utf8.h"std::vector<int> UTF8ToUTF32(const char* str) { std::vector<int> result; utf8::unchecked::utf8to32(str, str + strlen(str), back_inserter(result)); return result;}
最大长度
//计算最大长度int Max(std::string str1, std::string str2) { //类型转化 采用unicode编码 vector<vector<int>> pre = getRealWord(UTF8ToUTF32(str1.c_str())); vector<vector<int>> next = getRealWord(UTF8ToUTF32(str2.c_str())); int a = pre.size(); int b = next.size(); return a >b ? a : b;}
最小长度
int Min(int a,int b){ return a < b ? a : b;}
字符串是否部分包含
//求两个vector向量是否有交集void vectorIntersect(const vector<int>& v1, const vector<int>& v2, vector<int>& des)//求交集{ int i, j; i = j = 0;//定位到2个有序向量的头部 des.clear(); while (i < v1.size() && j < v2.size()) { if (v1[i] == v2[j]) //相等则为交集的元素之一 { des.push_back(v1[i]); i += 1; j += 1; } else if (v1[i] < v2[j]) //不相等时,指示较小元素额标记加一 { i += 1; } else { j += 1; } }}//判断字符串是否部分包含另一个字符串bool SearchPartStr(std::string str1, std::string str2){ vector<int> pre = UTF8ToUTF32(str1.c_str()); vector<int> next = UTF8ToUTF32(str2.c_str()); vector<int> result; vectorIntersect(pre, next, result); //要除去全包含的情况 if (str1 != str2&&!result.empty() && !SearchAllStr(str1.c_str(), str2.c_str()) && !SearchAllStr(str2.c_str(), str1.c_str())) { return true; } else { return false; }}
字符串是否全部包含
bool SearchAllStr(const char *pSource, const char *pSearch){ //在pSource查找字符pSearch是否存在 int lenSource = strlen(pSource); int lenSearch = strlen(pSearch); int firstCharNum = lenSource + 1; //判断搜索字符串是否比源字符串大 if (lenSearch > lenSource) { return false; } //遍历字符串 找到第一个相同的字符位置 firstCharNum for (int i = 0; i < lenSource; i++) { if (pSource[i] == pSearch[0]) { //找到目标字符 firstCharNum = i; break; } } if (firstCharNum > lenSource || (lenSource - firstCharNum) < lenSearch) { //没有找到相同字符 return false; } //首字符之后字符连续相同返回true int j = 1; for (int i = firstCharNum + 1; i < (firstCharNum + lenSearch); i++) { //遍历字符串 if (pSource[i] == pSearch[j]) { //找到目标字符 j++; } else { //递归调用自己 const char *newsource = pSource + firstCharNum + 1; return SearchAllStr(newsource, pSearch); } } return true;}
编辑距离
参考文章《编辑距离及编辑距离算法》
编辑距离矩阵
//编辑距离矩阵int ** GetEditMatrix(std::string str1, std::string str2) { vector<vector<int>> pre = getRealWord(UTF8ToUTF32(str1.c_str())); vector<vector<int>> next = getRealWord(UTF8ToUTF32(str2.c_str())); int max1 = pre.size(); int max2 = next.size(); int **ptr = new int *[max1 + 1]; for (int i = 0; i < max1 + 1; i++) { ptr[i] = new int[max2 + 1]; } for (int i = 0; i < max1 + 1; i++) { ptr[i][0] = i; } for (int i = 0; i < max2 + 1; i++) { ptr[0][i] = i; } for (int i = 1; i < max1 + 1; i++) { for (int j = 1; j < max2 + 1; j++) { int d; int temp = Min(ptr[i - 1][j] + 1, ptr[i][j - 1] + 1); if (pre[i - 1] == next[j - 1]) { d = 0; } else { d = 1; } ptr[i][j] = Min(temp, ptr[i - 1][j - 1] + d); } } return ptr;}
编辑距离
//编辑距离double GetEditDistance(std::string str1, std::string str2){ vector<vector<int>> pre = getRealWord(UTF8ToUTF32(str1.c_str())); vector<vector<int>> next = getRealWord(UTF8ToUTF32(str2.c_str())); int max1 = pre.size(); int max2 = next.size(); int **ptr = GetEditMatrix(str1, str2); int dis = ptr[max1][max2]; for (int i = 0; i < max1 + 1; i++) { delete[] ptr[i]; ptr[i] = NULL; } delete[] ptr; ptr = NULL; return dis;}
最大公共子串长度
//两个字符串之间最长的相同子字符串的长度int longestCommonSubstring(std::string s1, std::string s2){ vector<int> str1 =UTF8ToUTF32(s1.c_str()); vector<int> str2 =UTF8ToUTF32(s2.c_str()); int len1 = str1.size(); int len2 = str2.size(); if (len1 == 0 || len2 == 0)return 0; //定义二维数组dp[i][j] 代表串1从0~i这段与串2从0~j这段的公共子串的最大值 //赋初值dp[0~len1][0]=0 dp[0][0~len2]=0 vector<vector<int>> dp(len1 + 1, vector<int>(len2 + 1, 0)); for (int i = 1; i <= len1; i++) { for (int j = 1; j <= len2; j++) { if (str1[i - 1] == str2[j - 1]) { //若相等则上层值+1 dp[i][j] = dp[i - 1][j - 1] + 1; } else { //若不相等则等于交错值中的最大值 dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); } } } return dp[len1][len2];}
对角线改变元素行下标
//记录对角线上元素值第一次发生改变的元素行下标int GetFirstChange(std::string str1, std::string str2) { //类型转化 采用unicode编码 vector<vector<int>> pre = getRealWord(UTF8ToUTF32(str1.c_str())); vector<vector<int>> next = getRealWord(UTF8ToUTF32(str2.c_str())); int max1 = pre.size(); int max2 = next.size(); int **ptr = GetEditMatrix(str1,str2); vector<int> result; for (int i = 0; i < max1 + 1; i++) { for (int j = 0; j < max2 + 1; j++) { if (i == j&&i != 0 && j != 0) { if (ptr[i - 1][j - 1] != ptr[i][j]) { result.push_back(i); } } /*cout << ptr[i][j] << "";*/ } /*cout << endl;*/ } for (int i = 0; i < max1 + 1; i++) { delete[] ptr[i]; ptr[i] = NULL; } delete[] ptr; if (!result.empty()) { return result[0]; } else { return 0; }}
关联度计算
论文上的公式
优化前方案
优化后方案
代码实现
//计算关联度double GetCorrelation(std::string str1, std::string str2, int flag) { //optimiLen优化后的编辑距离 double correlation, correlA, correlB, optimiLen; vector<int> result; vector<vector<int>> pre = getRealWord(UTF8ToUTF32(str1.c_str())); vector<vector<int>> next = getRealWord(UTF8ToUTF32(str2.c_str())); int m = pre.size(); int n = next.size(); switch (flag) { case 0: //字符串全包含编辑距离替换成两串长度差的平均值 if (str1 != str2 && (SearchAllStr(str1.c_str(), str2.c_str()) || SearchAllStr(str2.c_str(), str1.c_str()))) { optimiLen = abs(GetEditDistance(str1, str2)- abs((m-n)/2)); } //字符串部分包含编辑距离替换最小字符串长度减去字符串交集部分长度后取平均值 else if (SearchPartStr(str1.c_str(), str2.c_str(),result) || SearchPartStr(str2.c_str(), str1.c_str(),result)) { int t = result.size(); optimiLen = abs(GetEditDistance(str1, str2) - abs((Min(m,n)-t) / 2)); } else { optimiLen = GetEditDistance(str1, str2); } /*cout << editLen << endl;*/ correlA = double(1 - ( optimiLen/ Max(str1, str2))); correlB = double(longestCommonSubstring(str1, str2) / double( optimiLen + longestCommonSubstring(str1, str2) + double((m - GetFirstChange(str1, str2)) / m))); /*cout << correlA << "," << correlB << endl;*/ //返回两种方法的最大值 if ( optimiLen != 0) { correlation = MaxCorrelation(correlA, correlB); } else { correlation = MaxCorrelation(GetCorrelation(str1,str2,1), GetCorrelation(str1, str2, 2)); } break; case 1: //方法一: 关联度=1-(编辑距离/词最大长度) correlation = double(1 - (GetEditDistance(str1, str2) / Max(str1, str2))); break; case 2: //方法二: 关联度=最大子串长度/(最大子串长度+编辑距离+(第一个字符串长度-对角线上元素值第一次发生改变的元素行下标)/第一个字符串长度)) correlation = double(longestCommonSubstring(str1, str2) / double(GetEditDistance(str1,str2) + longestCommonSubstring(str1, str2) + double((m - GetFirstChange(str1, str2)) / m))); break; case 3: //方法三: 关联度=1/(编辑距离+1) correlation = double(1 / (GetEditDistance(str1, str2) + 1)); break; default: break; } return correlation;}
运行结果
阅读全文
0 0
- 字符串关联度求解算法改进模型
- 迷宫求解的算法能否改进??
- 冷却算法综合排名改进模型
- 字符串相似度算法 递归与动态规划求解分析
- EM算法求解高斯混合模型
- EM算法求解混合伯努利模型
- 关联规则挖掘算法Aprior和FPGrowth对比与改进
- Kmp字符串匹配算法改进版
- 字符串匹配及kmp改进算法
- 倍增算法求解字符串的后缀数组
- 动态规划算法求解最大公共字符串
- 字符串匹配--BM算法的改进的算法 Sunday Algorithm
- 一种基于邻接图模型的改进LDA算法
- 冷却算法综合排名改进模型-R实现代码
- 字符串查找问题,求解字符串的周期(KMP算法)
- 机器学习--EM算法求解高斯混合模型
- 采用EM算法求解高斯混合模型参数
- 用EM算法求解高斯混合模型
- 纯js对根据table中的两个字段对table进行去重操作(精华版)
- eclipse项目转到as项目报错
- scala/idea/java
- poj 2406 Power Strings
- 01 Anykey登录界面
- 字符串关联度求解算法改进模型
- 初识JavaScript DOM
- response.setContentType()的作用及参数
- C++之善用PIMPL技巧
- 修复线上问题,引起新的bug-总结
- 关于郑渊洁的最后一段话
- Hadoop YARN常见问题以及解决方案
- Error building SqlSession.
- OpenCV图像处理(2)-空间变换,几何变换,阈值处理