note 109564 added to function.similar-text
| From: | (a) | Date: | Sun, 29 Jul 2012 05:50:14 +0000 |
| Subject: | note 109564 added to function.similar-text | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-189449@lists.php.net to get a copy of this message | ||
To spam hater and others: this function has been broken for a very long time. The devs unfortunately
keep ignoring it. Not only swapping the two strings give different results, it gives wrong results
too.
http://bugs.php.net/bug.php?id=62648
<?php
echo similar_text("test", "cert");
echo ",";
echo similar_text("cert", "test");
?>
Prints 1,2 instead of 2,2. Also:
<?php
$s1 = 'biocompatibilitystudiesofironoxidedextrinthinfilmsbacdetundgakslfnnd';
$s2 = 'studyofironoxidenanoparticlescoatedwithdextrinobtainedbybcgagsfddteuhdgavdjfkdbey';
echo similar_text($s1, $s2);
echo ",";
echo similar_text($s2, $s1);
?>
Prints 34,32 instead of 35,35. Both are wrong!
The similar_text() function computes the length of the longest subsequence; google "longest
subsequence problem" (LCS). In the above case, that is
"studofironoxidedextrintinbcdtudgafd" which has 35 chars.
The earlier implementation in these comments of an LCS length function didn't actually work for
me.
Here's a functional and direct replacement of the broken similar_text(). Note it is much slower
than similar_text(), since similar_text is a native C function, but that's buggy and this
works:
<?php
function similar_text_fix ($str1, $str2, &$percent = null)
{
$len1 = strlen($str1);
$len2 = strlen($str2);
// two-dim array, init first row and column to zero
$a = array_fill(1, $len1, array(0));
$a[0] = array_fill(0, $len2 + 1, 0);
for ($i = 1; $i <= $len1; ++$i)
for ($j = 1; $j <= $len2; ++$j)
if ($str1{$i-1} == $str2{$j-1})
$a[$i][$j] = $a[$i-1][$j-1] + 1;
else
$a[$i][$j] = $a[$i][$j-1] > $a[$i-1][$j] ? $a[$i][$j-1] : $a[$i-1][$j];
$percent = $a[$len1][$len2] * 200 / ($len1 + $len2);
return $a[$len1][$len2];
}
?>
Here's a test:
<?php
echo similar_text($s1, $s2, $p);
echo ",";
echo similar_text($s2, $s1);
echo ",$p";
// 35,35,46.979865771812
?>
Regards
Regards
----
Server IP: 69.147.83.197
Probable Submitter: 131.111.7.72
----
Manual Page -- http://www.php.net/manual/en/function.similar-text.php
Edit -- https://master.php.net/note/edit/109564
Del: integrated -- https://master.php.net/note/delete/109564/integrated
Del: useless -- https://master.php.net/note/delete/109564/useless
Del: bad code -- https://master.php.net/note/delete/109564/bad+code
Del: spam -- https://master.php.net/note/delete/109564/spam
Del: non-english -- https://master.php.net/note/delete/109564/non-english
Del: in docs -- https://master.php.net/note/delete/109564/in+docs
Del: other reasons-- https://master.php.net/note/delete/109564
Reject -- https://master.php.net/note/reject/109564
Search -- https://master.php.net/manage/user-notes.php