PHP中计算字符串相似度的函数代码


Posted in PHP onDecember 29, 2012

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代码也是用于比较两个字符串的相似度,直接贴出代码:

<?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,明显准确的多。

PHP 相关文章推荐
用PHP代替JS玩转DOM的思路及示例代码
Jun 15 PHP
ThinkPHP页面跳转success与error方法概述
Jun 25 PHP
PHP开发框架Laravel数据库操作方法总结
Sep 03 PHP
php图片处理函数获取类型及扩展名实例
Nov 19 PHP
php获取数组元素中头一个数组元素值的实现方法
Dec 20 PHP
php基于socket实现SMTP发送邮件的方法
Mar 05 PHP
PHP整合七牛实现上传文件
Jul 03 PHP
1亿条数据如何分表100张到Mysql数据库中(PHP)
Jul 29 PHP
php利用云片网实现短信验证码功能的示例代码
Nov 18 PHP
php使用curl伪造来源ip和refer的方法示例
May 08 PHP
Laravel 实现Controller向blade前台模板赋值的四种方式小结
Oct 22 PHP
Laravel5.1 框架数据库操作DB运行原生SQL的方法分析
Jan 07 PHP
PHP flock 文件锁详细介绍
Dec 29 #PHP
PHP生成唯一的促销/优惠/折扣码(附源码)
Dec 28 #PHP
PHP中函数rand和mt_rand的区别比较
Dec 26 #PHP
php中unlink()、mkdir()、rmdir()等方法的使用介绍
Dec 21 #PHP
php和javascript之间变量的传递实现代码
Dec 19 #PHP
ajax php传递和接收变量实现思路及代码
Dec 19 #PHP
PHP编码转换函数 自动转换字符集支持数组转换
Dec 16 #PHP
You might like
[FAQ]PHP中的一些常识:类篇
2006/10/09 PHP
PHP strncasecmp字符串比较的小技巧
2011/01/04 PHP
smarty实现多级分类的方法
2014/12/05 PHP
php的4种常见运行方式
2015/03/20 PHP
PHP htmlspecialchars_decode()函数用法讲解
2019/03/01 PHP
php中array_fill函数的实例用法
2021/03/02 PHP
在JavaScript中,为什么要尽可能使用局部变量?
2009/04/06 Javascript
javascript 正则表达式相关应介绍
2012/11/27 Javascript
JavaScript实现数字数组正序排列的方法
2015/04/06 Javascript
JS扩展方法实例分析
2015/04/15 Javascript
每天一篇javascript学习小结(属性定义方法)
2015/11/19 Javascript
JS JSOP跨域请求实例详解
2016/07/04 Javascript
最实用的jQuery分页插件
2016/10/09 Javascript
javascript基本数据类型及类型检测常用方法小结
2016/12/14 Javascript
Vue中JS动画与Velocity.js的结合使用
2019/02/13 Javascript
Vue.js实现备忘录功能
2019/06/26 Javascript
layui表格分页 记录勾选的实例
2019/09/02 Javascript
100行代码实现vue表单校验功能(小白自编)
2019/11/19 Javascript
[44:10]2018DOTA2亚洲邀请赛 4.5 淘汰赛 EG vs VP 第一场
2018/04/06 DOTA
用Python编写简单的定时器的方法
2015/05/02 Python
python实现事件驱动
2018/11/21 Python
softmax及python实现过程解析
2019/09/30 Python
python3.6使用SMTP协议发送邮件
2020/05/20 Python
Expedia法国:全球最大在线旅游公司
2018/09/30 全球购物
SCDKey德国:全球领先的数字游戏市场
2019/04/09 全球购物
大专生简历的自我评价
2013/11/26 职场文书
大学生简历的个人自我评价
2013/12/04 职场文书
办公室内勤岗位职责范本
2013/12/09 职场文书
教师自我鉴定范文
2014/03/20 职场文书
社区党的群众路线教育实践活动剖析材料
2014/10/09 职场文书
2014年小学安全工作总结
2014/12/04 职场文书
建立共青团委员会的请示
2019/04/02 职场文书
文明医院的标语集锦!
2019/07/24 职场文书
Nest.js参数校验和自定义返回数据格式详解
2021/03/29 Javascript
Python自动化测试PO模型封装过程详解
2021/06/22 Python
我去timi了,一起去timi是什么意思?
2022/04/13 杂记