PHP有个计算两个文本字符串相似度的函数similar_text(),可以得出一个百分比来表示两个字符串的相似程度。效果如下:

similar_text('aaaa', 'aaaa', $percent);

var_dump($percent);

//float(100)

similar_text('aaaa', 'aaaabbbb', $percent);

var_dump($percent);

//float(66.666666666667)

similar_text('abcdef', 'aabcdefg', $percent);

var_dump($percent);

//float(85.714285714286)

利用这个函数,可以用来做模糊搜索的功能,或者其他需要模糊匹配的功能。最近我在验证码识别研究中的特征匹配一步上涉及到了这个函数。

但这个函数具体使用了怎样的算法呢?我研究了他的底层实现,总结为三步:

(1)找出两个字符串中相同部分最长的一段;

(2)再用同样的方法在剩下的两段中分别找出相同部分最长的一段,以此类推,直到没有任何相同部分;

(3)相似度 = 所有相同部分的长度之和 * 2 / 两个字符串的长度之和;

我研究的源代码版本是PHP 5.4.6,相关的代码位于文件php-5.4.6/ext/standard/string.c的第2951~3031行。以下是我加过注释后源代码。

//找出两个字符串中相同部分最长的一段

static void php_similar_str( const char *txt1, int len1, const char *txt2, int len2, int * pos1, int * pos2, int * max )

{

char * p, *q;

char * end1 = (char *) txt1 + len1;

char * end2 = (char *) txt2 + len2;

int l;

*max = 0;

/* 以第一个字符串为基准开始遍历 */

for ( p = (char *) txt1; p < end1; p++ )

{

/* 遍历第二个字符串 */

for ( q = (char *) txt2; q < end2; q++ )

{

/* 发现有字符相同,继续循环找,l为相同部分的长度 */

for ( l = 0; (p + l < end1) && (q + l < end2) && (p[l] == q[l]); l++ )

;

/* 冒泡方法找出最长的一个l,并记住相同部分的开始位置 */

if ( l > *max )

{

*max    = l;

*pos1    = p - txt1;

*pos2    = q - txt2;

}

}

}

}

//计算两个字符串的相同部分的总长度

static int php_similar_char( const char *txt1, int len1, const char *txt2, int len2 )

{

int sum;

int pos1, pos2, max;

/* 找出两个字符串相同部分最长的一段 */

php_similar_str( txt1, len1, txt2, len2, &pos1, &pos2, &max );

/* 这里是对sum的初始赋值,也是对max值的判断 */

/* 如果max为零,表示两个字符串没有任何相同的字符,也就会跳出if */

if ( (sum = max) )

{

/* 对前半段递归,相同段长度累加 */

if ( pos1 && pos2 )

{

sum += php_similar_char( txt1, pos1,

txt2, pos2 );

}

/* 对后半段递归,相同段长度累加 */

if ( (pos1 + max < len1) && (pos2 + max < len2) )

{

sum += php_similar_char( txt1 + pos1 + max, len1 - pos1 - max,

txt2 + pos2 + max, len2 - pos2 - max );

}

}

return(sum);

}

//PHP函数定义

PHP_FUNCTION( similar_text )

{

char *t1, *t2;

zval **percent = NULL;

int ac = ZEND_NUM_ARGS();

int sim;

int t1_len, t2_len;

/* 检查参数合法性 */

if ( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "ss|Z", &t1, &t1_len, &t2, &t2_len, &percent ) == FAILURE )

{

return;

}

/* 如果有第三个参数 */

if ( ac > 2 )

{

convert_to_double_ex( percent );

}

/* 如果两个字符串长度都为0,返回0 */

if ( t1_len + t2_len == 0 )

{

if ( ac > 2 )

{

Z_DVAL_PP( percent ) = 0;

}

RETURN_LONG( 0 );

}

/* 调用上面的函数,计算两个字符串的相似度 */

sim = php_similar_char( t1, t1_len, t2, t2_len );

/* 可以看到percent的计算公式 */

if ( ac > 2 )

{

Z_DVAL_PP( percent ) = sim * 200.0 / (t1_len + t2_len);

}

RETURN_LONG( sim );

}

另外,PHP还提供了另外一个计算字符串相似度的函数levenshtein(),通过计算两个字符串的编辑距离来表示字符串相似度,这也是一种很常见的算法。

levenshtein()的性能相比similar_text()要好一些,因为通过前面的代码分析可以看到,similar_text()的复杂度是O(n^3),n表示最长字符串的长度,而levenshtein()的复杂度为O(m*n),m与n分别为两个字符串的长度。

文本相似度php,分析php计算文本字符串相似度函数similar_text()的原理相关推荐

  1. 使用simhash计算文本相似度

    1. 使用simhash计算文本相似度 2. 使用余弦相似度计算文本相似度 3. 使用编辑距离计算文本相似度 4. jaccard系数计算文本相似度 文本相似度计算常用于网页去重以及NLP里文本分析等 ...

  2. 使用余弦相似度计算文本相似度

    1. 使用simhash计算文本相似度 2. 使用余弦相似度计算文本相似度 3. 使用编辑距离计算文本相似度 4. jaccard系数计算文本相似度 2.向量余弦计算文本相似度 2.1 原理 余弦相似 ...

  3. 使用编辑距离计算文本相似度

    1. 使用simhash计算文本相似度 2. 使用余弦相似度计算文本相似度 3. 使用编辑距离计算文本相似度 4. jaccard系数计算文本相似度 3. 最小编辑距离计算文本相似度 3.1 编辑距离 ...

  4. python比较两个字符串相似度_详解Python 字符串相似性的几种度量方法

    字符串的相似性比较应用场合很多,像拼写纠错.文本去重.上下文相似性等. 评价字符串相似度最常见的办法就是:把一个字符串通过插入.删除或替换这样的编辑操作,变成另外一个字符串,所需要的最少编辑次数,这种 ...

  5. python字符串相似度去重_Python 字符串相似性的几种度量方法

    字符串的相似性比较应用场合很多,像拼写纠错.文本去重.上下文相似性等. 评价字符串相似度最常见的办法就是:把一个字符串通过插入.删除或替换这样的编辑操作,变成另外一个字符串,所需要的最少编辑次数,这种 ...

  6. python字符串相似度去重_详解Python 字符串相似性的几种度量方法

    字符串的相似性比较应用场合很多,像拼写纠错.文本去重.上下文相似性等. 评价字符串相似度最常见的办法就是:把一个字符串通过插入.删除或替换这样的编辑操作,变成另外一个字符串,所需要的最少编辑次数,这种 ...

  7. python字符串怎么计算_Python字符串相似性的几种计算方法

    码农公社  210.net.cn  210= 1024  10月24日一个重要的节日--码农(程序员)节 字符串的相似性比较应用场合很多,像拼写纠错.文本去重.上下文相似性等. 评价字符串相似度最常见 ...

  8. 使用余弦相似度算法计算文本相似度-数学

    20211201 也就是效果 皮尔逊>余弦>欧式 余弦相似度的局限 皮尔逊的优势,相当于是改进版余弦相似度 欧式与 余弦 欧式侧重于直线距离 归一化之后的欧式和余弦的效果也不同 比如 0, ...

  9. 使用余弦相似度算法计算文本相似度

    在求相似度的时候经常会有以下一些方法, 1.基于词向量 余弦相似度 曼哈顿距离 欧几里得距离 明式距离(是前两种距离测度的推广),在极限情况下的距离是切比雪夫距离 2.基于字符的 编辑距离 simha ...

最新文章

  1. android自动化测试工具之monkey
  2. matlab 双音多频 接收端检测到的号码,信号语音论文,关于基于MATLAB的双音多频信号识别相关参考文献资料-免费论文范文...
  3. 一段js实现复制文本内容到剪切板
  4. 好用的记事本_分类记事本软件哪个好用?大家推荐一个苹果手机用的分类记事本便签呗...
  5. git入门(廖雪峰老师)
  6. python 参数个数 同名函数_Python——函数的参数
  7. trang.jar转换xml到Javabean
  8. (03)FPGA与CPLD区别
  9. 图片变色_一张图看懂手机CMF史,附带手机渐变色工艺解析
  10. 破圈!不止于浏览器,WebAssembly 2020 大事记
  11. 天天写代码,觉得自己特别苦逼?嗯,还有20年AI就来解放你
  12. python reference理解
  13. 数据库--sql查询某一时间段数据
  14. 学习网站及工具地址汇总
  15. Cocos2d-x游戏开发之骨骼动画详解-Spine
  16. 在word中如何制作问卷调查?原来是使用word控件技巧!
  17. layuiadmin上手好难_滑步车比赛好拍吗?
  18. 第八十七篇 朴素贝叶斯
  19. ★人眼到底等于多少像素 ?
  20. 大数据和云计算发展前景怎样?

热门文章

  1. 悟 - 见路不走
  2. 转码日记:3days
  3. 1076 Wifi密码(15 分)
  4. 学习 Redis - 3. 进阶
  5. 常用Lambda表达式
  6. 百天实习记 ---2015南京南大富士通实习感想
  7. 一键分享到QQ空间、QQ好友、新浪微博、微信代码
  8. 一张图看明白UML类图中的6种关系
  9. 我们在二楼有一个计算机教室用英语怎么说,人教英语新起点三年级 Unit2 知识...
  10. 1+X Web前端等级考证 | 2020 12月Web前端开发中级实操 (模拟试题第四套) 附答案