码迷,mamicode.com
首页 > 其他好文 > 详细

搜索里的相似度计算-最长公共字串

时间:2014-07-22 22:53:35      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   使用   os   io   

相似度计算的任务是根据两段输入文本的相似度返回从0到1之间的相似度值:完全不相似,则返回0,;完全相同,返回1.衡量两端文字距离的常用方法有:海明距离(Hamming distance),编辑距离,欧氏距离,文档向量的夹角余弦距离,最长公共字串。

1. 余弦相似度

把两篇文档看作是词的向量,如果x,y为两篇文档的向量,则:Cos(x, y) = (x * y) / (||x|| * ||y||)

使用Hashmap可以很方便的把这个计算出来

2. 最长公共字串(Longest Common Subsequence, LCS)

 

假设有串s1 = {a,b,c,b,d,a,b}, s2={b,d,c,a,b,a}, s1和s2的最长公共字串应当有3个”bdab”,”bcab”,”bcba”。

这又是一个动态规划法的应用,思维过程就简单带过,生成一个s1.size + 1 X s2.size+1的矩阵,行和列分别是s1和s2的每个字母,填充矩阵,如果对应的两个字母相同,就把斜上角的元素+1,填充到当前矩阵位置,如果不同,取该位置相邻左边及上边的最大值,一直把矩阵填满,最右下角的矩阵值就是最长公共字串的长度。

      b,d,c,a,b,a

   0,0,0,0,0,0,0,
a  0,0,0,0,1,1,1,
b  0,1,1,1,1,2,2,
c  0,1,1,2,2,2,2,
b  0,1,1,2,2,3,3,
d  0,1,2,2,2,3,3,
a  0,1,2,2,3,3,4,
b  0,1,2,2,3,4,4

得到最长公共字串的矩阵后,剩下的工作就是回溯。

如果当前位置的s1字符和s2字符相同,则是相同的数值。

如果不同,则要向上或向左移动,移动到大的一边,与填充矩阵的逻辑对应。

如果是相同呢?

如果只求其中一个公共字串,逻辑比较简单,随便想上或者向左

如果要求所有的公共字串,则每一边都有可能,可以简单用递归解决。

好了。说这么多,上代码。

 

 1 #encoding:utf-8
 2 require matrix
 3 class Matrix
 4   def []=(i, j, x)
 5     @rows[i][j] = x
 6   end
 7 end
 8 
 9 # 最长公共字串
10 def start
11   $s1 = abcbdab
12   $s2 = bdcaba
13   $num = Matrix.zero($s1.size + 1, $s2.size + 1)
14   puts "Row = #{$num.row_size}, col = #{$num.column_size}"
15 
16   for i in 1..$s1.size
17     for j in 1..$s2.size
18       if $s1[i - 1] == $s2[j - 1]
19         $num[i, j] = $num[i-1, j-1] + 1
20       else
21         $num[i, j] = [$num[i-1, j], $num[i, j-1]].max
22       end
23     end
24   end
25 
26   puts "最长公共字串的长度是#{$num[$s1.size, $s2.size]}"
27   $num.each_with_index { |val, row, col| print val,,; puts if (col + 1) % $num.column_size == 0}
28 
29   # 回溯路径
30   $result = []
31   $lcs_length = $num[$s1.size, $s2.size]
32   s1position = $s1.size
33   s2position = $s2.size
34   loop_path(s1position, s2position, ‘‘)
35   $result.each {|x| puts "lcs: #{x}"}
36 
37   puts "one path is: #{one_loop_path(s1position,s2position, ‘‘)}"
38 end
39 
40 def one_loop_path(s1position, s2position, result)
41   while s1position != 0 and s2position != 0
42     if $s1[s1position - 1] == $s2[s2position - 1]
43       result << $s1[s1position - 1]
44       s2position -= 1
45       s1position -= 1
46       next
47     end
48 
49     if $num[s1position, s2position - 1] >= $num[s1position - 1, s2position]
50       s2position -= 1
51     else
52       s1position -= 1
53     end
54   end
55   result
56 end
57 
58 def loop_path(s1position, s2position, result)
59   while s1position != 0 and s2position != 0
60     if $s1[s1position - 1] == $s2[s2position - 1]
61       result << $s1[s1position - 1]
62       s2position -= 1
63       s1position -= 1
64       next
65     end
66 
67     if $num[s1position, s2position - 1] > $num[s1position - 1, s2position]
68       s2position -= 1
69     elsif $num[s1position, s2position - 1] < $num[s1position - 1, s2position]
70       s1position -= 1
71     elsif $num[s1position, s2position - 1] == $num[s1position - 1, s2position]
72       leftpath = result.clone
73       uppath = result.clone
74       loop_path(s1position, s2position - 1, leftpath)
75       loop_path(s1position - 1, s2position, uppath)
76       break
77     end
78   end
79   $result << result.reverse! if result.size == $lcs_length
80   # $result << result.reverse! if result.size == $lcs_length
81 end
82 
83 start

搜索里的相似度计算-最长公共字串,布布扣,bubuko.com

搜索里的相似度计算-最长公共字串

标签:style   blog   color   使用   os   io   

原文地址:http://www.cnblogs.com/daoyou/p/3855181.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!