思路是:把字符串的字符放入一个字典中,计算他们(相同的个数/开平方(字符串1的个数*字符串2的个数),得到相似度
比如要比较 "中国" 和 "中"
则字典中存放的是
中 | 国 | |
0(第一个字符串) | 1(存在) | 1(存在) |
1(第二个字符串) | 1(存在) | 0(不存在) |
计算相同的个数: 计算中字: [中][0]*[中][1]=1*1=1 计算国字:[国][0]*[国][1]=1*0=0 则相同的个数为:1+0=1
计算字符串1的个数: [中][0]*[中][0]=1*1=1 [国][0]*[国][0]=1*1=1 则 字符串一的个数为: 1+1=2
计算字符串2的个数: [中][1]*[中][1]=1*1=1 [国][0]*[国][0]=0*0=0 则 字符串一的个数为: 1+0=1
相似度为: 相同个数/开方(字符串1的个数*字符2的个数) 1/sqrt(2*1)=0.7
类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace txtSim
{
class TxtSim
{
public static double GetSimilarity(string doc1, string doc2)
{
if (doc1 != null && doc1.Trim() != string.Empty &&
doc2 != null && doc2.Trim() != string.Empty)
{
Dictionary<Int16, int[]> algMap = new Dictionary<Int16, int[]>();
for (int i = 0; i < doc1.Length; i++)
{
if (IsHanZi(doc1[i]))
{
Int16 chval = GetGB2312Id(doc1[i]);
if (chval != -1)
{
if (algMap.ContainsKey(chval))
{
algMap[chval][0] += 1;
}
else
{
algMap.Add(chval, new int[2]);
algMap[chval][0] = 1;
}
}
}
}
for (int i = 0; i < doc2.Length; i++)
{
if (IsHanZi(doc2[i]))
{
Int16 chval = GetGB2312Id(doc2[i]);
if (chval != -1)
{
if (algMap.ContainsKey(chval))
{
algMap[chval][1] += 1;
}
else
{
algMap.Add(chval, new int[2]);
algMap[chval][1] = 1;
}
}
}
}
// 对比计算
double rst = 0.0d;
double sqdoc1 = 0;
double sqdoc2 = 0;
double denominator = 0;
foreach (KeyValuePair<Int16, int[]> kv in algMap)
{
//利用两个都存在时(都为1,1*1=1),一个存在时为(1*0=0),d都不存在时为(0*0=0)求出相同的个数
denominator += kv.Value[0] * kv.Value[1];
//求出字符串1的字符个数
sqdoc1 += kv.Value[0] * kv.Value[0];
//求出字符串2的字符个数
sqdoc2 += kv.Value[1] * kv.Value[1];
}
rst = denominator / Math.Sqrt(sqdoc1 * sqdoc2);
return rst;
}
else
{
return 0.0d;
}
}
public static bool IsHanZi(char ch)
{
bool rst = false;
string tmp = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
rst = tmp.IndexOf(ch) > -1;
if (!rst)
{
rst = (ch >= 0x4e00 && ch <= 0x9fa5);
}
return rst;
}
public static Int16 GetGB2312Id(char ch)
{
try
{
byte[] buf = Encoding.GetEncoding("GB2312").GetBytes(ch.ToString());
if (buf.Length != 2)
{
return (Int16)(buf[0] & 0xff);
}
int b0 = (int)(buf[0] & 0xff) - 161;
int b1 = (int)(buf[1] & 0xff) - 161;
return (Int16)(b0 * 94 + b1);
}
catch { }
return -1;
}
}
}
GetGB2312Id主要是把中文改成编号来作为字典标识
比如"中"字编号为20013即 [中][0] 在字典中为[20013][0]
实例:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace txtSim
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var s = TxtSim.GetSimilarity(this.textBox1.Text.Trim(), this.textBox2.Text.ToString().Trim());
this.label1.Text = s.ToString();
}
}
}