这里一个比较合理的思路。
如果最长公共子序列长为k, 文本1长为n1, 文本2长为n2,则相似度为 (2 * k) / (n1 + n2)
结果如下:
代码如下:
#include <iostream>
#include <string>
#include <windows.h>
#include <algorithm>
#include <cmath>
#include <vector>
#include <tchar.h>
using namespace std;
class Matcher{
public:
Matcher(wchar_t s1[], int n1, wchar_t s2[], int n2){
this->s1 = s1;
this->s2 = s2;
this->n1 = n1;
this->n2 = n2;
buf = new int*[n1 + 1];
for(int i = 0; i <= n1; i++){
buf[i] = new int[n2 + 1];
for(int j = 0; j <= n2; j++){
buf[i][j] = 0;
}
}
}
~Matcher(){
for(int i = 0; i <= n1; i++){
delete[] buf[i];
}
delete[] buf;
}
/*计算相似度*/
double match(){
//先排个序
sort(s1, s1 + n1);
sort(s2, s2 + n2);
int maxCommonLen = matchAct(n1, n2);
return 2 * maxCommonLen * 1.0 / (n1 + n2);
}
private:
wchar_t* s1;
wchar_t* s2;
int n1;
int n2;
int** buf;
/*查找最长公共子序列长度*/
int matchAct(int n1, int n2){
if(n1 <= 0 || n2 <= 0){
return 0;
}
//Dynamic Planning--如果去掉以下三个if,则是普通的分治
if(buf[n1 - 1][n2 - 1] == 0){
buf[n1 - 1][n2 - 1] = matchAct(n1 - 1, n2 - 1);
}
if(buf[n1 - 1][n2] == 0){
buf[n1 - 1][n2] = matchAct(n1 - 1, n2);
}
if(buf[n1][n2 - 1] == 0){
buf[n1][n2 - 1] = matchAct(n1, n2 - 1);
}
if(s1[n1 - 1] == s2[n2 - 1]){
return buf[n1 - 1][n2 - 1] + 1;
}
return max(buf[n1 - 1][n2],
buf[n1][n2 - 1]);
}
};
int main()
{
wchar_t s1[] = L"a1b2c3d4";
wchar_t s2[] = L"1452364";
Matcher m1(s1, 8, s2, 7);
cout << "相似度:" << m1.match() << endl;
wchar_t s3[] = L"我和我的祖国";
wchar_t s4[] = L"国祖的我和我";
Matcher m2(s3, 6, s4, 6);
cout << "相似度:" << m2.match() << endl;
wchar_t s5[] = L"东方甲乙木";
wchar_t s6[] = L"南方丙丁火";
Matcher m3(s5, 5, s6, 5);
cout << "相似度:" << m3.match() << endl;
return 0;
}