similar_text — 计算两个字符串的相似度
int similar_text ( string $first , string $second [, float &$percent ] )
$first 必需。规定要比较的第一个字符串。
$second 必需。规定要比较的第二个字符串。
$percent 可选。规定供存储百分比相似度的变量名。
两个字符串的相似程度计算依据 Oliver [1993] 的描述进行。注意该实现没有使用 Oliver 虚拟码中的堆栈,但是却进行了递归调用,这个做法可能会导致整个过程变慢或变快。也请注意,该算法的复杂度是 O(N**3),N 是最长字符串的长度。
比如我们想找字符串abcdefg和字符串aeg的相似度:
$first = "abcdefg";
$second = "aeg";
echo similar_text($first, $second);结果输出3.如果想以百分比显示,则可使用它的第三个参数,如下:
$first = "abcdefg";
$second = "aeg";
similar_text($first, $second, $percent);
echo $percent;
similar_text函数的使用及实现过程。similar_text() 函数主要是用来计算两个字符串的匹配字符的数目,也可以计算两个字符串的相似度(以百分比计)。与 similar_text() 函数相比,我们今天要介绍的 levenshtein() 函数更快。不过,similar_text() 函数能通过更少的必需修改次数提供更精确的结果。在追求速度而少精确度,并且字符串长度有限时可以考虑使用 levenshtein() 函数。
使用说明
先看手册上 levenshtein() 函数的说明:
levenshtein() 函数返回两个字符串之间的 Levenshtein 距离。
Levenshtein 距离,又称编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
例如把 kitten 转换为 sitting:
sitten (k→s)
sittin (e→i)
sitting (→g)levenshtein() 函数给每个操作(替换、插入和删除)相同的权重。不过,您可以通过设置可选的 insert、replace、delete 参数,来定义每个操作的代价。
语法:
levenshtein(string1,string2,insert,replace,delete)
参数 描述
•string1 必需。要对比的第一个字符串。
•string2 必需。要对比的第二个字符串。
•insert 可选。插入一个字符的代价。默认是 1。
•replace 可选。替换一个字符的代价。默认是 1。
•delete 可选。删除一个字符的代价。默认是 1。
提示和注释
•如果其中一个字符串超过 255 个字符,levenshtein() 函数返回 -1。
•levenshtein() 函数对大小写不敏感。
•levenshtein() 函数比 similar_text() 函数更快。不过,similar_text() 函数提供需要更少修改的更精确的结果。
例子
<?php
echo levenshtein("Hello World","ello World");
echo "<br />";
echo levenshtein("Hello World","ello World",10,20,30);
?>
输出: 1 30
以下是补充:
php默认有个函数similar_text()用于计算字符串之间的相似度,该函数也可以计算两个字符串的相似度(以百分比计)。不过这个函数感觉对中文计算很不准确比如:
echo similar_text("吉林禽业公司火灾已致112人遇难","吉林宝源丰禽业公司火灾已致112人遇难");
这两个新闻标题其实都是一样的,如果使用similar_text()相似对结果为:42,即只相似42%,所以这个感觉很不靠谱,今天刚好收集到一段PHP代码也是用于比较两个字符串的相似度,直接贴出代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
<?php class LCS { var $str1 ; var $str2 ; var $c = array (); /*返回串一和串二的最长公共子序列 */ function getLCS( $str1 , $str2 , $len1 = 0, $len2 = 0) { $this ->str1 = $str1 ; $this ->str2 = $str2 ; if ( $len1 == 0) $len1 = strlen ( $str1 ); if ( $len2 == 0) $len2 = strlen ( $str2 ); $this ->initC( $len1 , $len2 ); return $this ->printLCS( $this ->c, $len1 - 1, $len2 - 1); } /*返回两个串的相似度 */ function getSimilar( $str1 , $str2 ) { $len1 = strlen ( $str1 ); $len2 = strlen ( $str2 ); $len = strlen ( $this ->getLCS( $str1 , $str2 , $len1 , $len2 )); return $len * 2 / ( $len1 + $len2 ); } function initC( $len1 , $len2 ) { for ( $i = 0; $i < $len1 ; $i ++) $this ->c[ $i ][0] = 0; for ( $j = 0; $j < $len2 ; $j ++) $this ->c[0][ $j ] = 0; for ( $i = 1; $i < $len1 ; $i ++) { for ( $j = 1; $j < $len2 ; $j ++) { if ( $this ->str1[ $i ] == $this ->str2[ $j ]) { $this ->c[ $i ][ $j ] = $this ->c[ $i - 1][ $j - 1] + 1; } else if ( $this ->c[ $i - 1][ $j ] >= $this ->c[ $i ][ $j - 1]) { $this ->c[ $i ][ $j ] = $this ->c[ $i - 1][ $j ]; } else { $this ->c[ $i ][ $j ] = $this ->c[ $i ][ $j - 1]; } } } } function printLCS( $c , $i , $j ) { if ( $i == 0 || $j == 0) { if ( $this ->str1[ $i ] == $this ->str2[ $j ]) return $this ->str2[ $j ]; else return "" ; } if ( $this ->str1[ $i ] == $this ->str2[ $j ]) { return $this ->printLCS( $this ->c, $i - 1, $j - 1). $this ->str2[ $j ]; } else if ( $this ->c[ $i - 1][ $j ] >= $this ->c[ $i ][ $j - 1]) { return $this ->printLCS( $this ->c, $i - 1, $j ); } else { return $this ->printLCS( $this ->c, $i , $j - 1); } } } $lcs = new LCS(); //返回最长公共子序列 $lcs ->getLCS( "hello word" , "hello china" ); //返回相似度 echo $lcs ->getSimilar( "吉林禽业公司火灾已致112人遇难" , "吉林宝源丰禽业公司火灾已致112人遇难" ); |
同样输出结果为:0.90322580645161,明显准确的多。