note 109564 deleted from function.similar-text by danbrown

From: Date: Mon, 30 Jul 2012 15:47:54 +0000
Subject: note 109564 deleted from function.similar-text by danbrown
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-189476@lists.php.net to get a copy of this message
Note Submitter: normadize (a) gmail (d) com ---- 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

« previous php.notes (#189476) next »