思路是:把字符串的字符放入一个字典中,计算他们(相同的个数/开平方(字符串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; } } }
比如"中"字编号为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(); } } }