Jaro Winkler algoritması yazım hatası olsa bile doğru sonuca erişme

Arama motorları bizi nasıl anlıyor yanlış yazsak da doğru sonuca nasıl erişebiliyor? Bir programcının mutlaka ihtiyaç duyacağı bir algoritma. Bu algoritma yazım hatalarına rağman doğru sonuca erişmenizi sağlıyor. Söz konusu algoritmanın adı Jaro Winkler. Algoritma 1990 da William E. Winkler tarafından Jaro mesafe metriği kullanılarak geliştirildi.

https://wikimedia.org/api/rest_v1/media/math/render/svg/649ef8b1f712410856419f3525345c5ac7b3e88e

Ben bunu ilk olarak formlara isimlerini yanlış kodlayan öğrencileri tespit etmek için kullanmıştım. Bir zamanlar lys de açık uçlu sorular vardı bunun tespitinde de kullanmıştım. Genel kullanımda nasıl işinize yarar? Varsayalım Birçok müşteriniz var ve bunların bir kısmı yabancı uyruklu. Veri tabanından veriyi tam eşleşme ile aradağınız için bunu bulmanız çok zor olabilir. Örneğin Mpabpe olarak aramanız gereken veri futbolcu isminden yanılarak Mbappe olarak arıyorsunuz. ve bulamıyorsunuz. Bu çok normal çünkü daha 2. harfte patladınız. Ama bunu Jaro Winkler algoritmasından geçirdiğinizde size binlerce kişi ismi arasından 0.96 eşleşme ile bunu bulacaktır. 1e 1 eşleşmeye ne kadar yakın bir sonuç öyle değil mi? Bu arama yapan kullanıcıyı fazlasıyla tatmin edecektir

https://wikimedia.org/api/rest_v1/media/math/render/svg/03671087a717f53684606025f53b650fd134bac7

Algoritmanın php fonksiyon hali aşağıdadır.

$hedef="Mpabpe"; $kaynak="Mbappe";

Jaro($hedef, $kaynak); 

// Şeklinde kullanabilirsiniz.

 

function getCommonCharacters( $string1, $string2, $allowedDistance ){

$str1_len = strlen($string1);
$str2_len = strlen($string2);
$temp_string2 = $string2;

$commonCharacters='';

for( $i=0; $i < $str1_len; $i++){

$noMatch = True;

// compare if char does match inside given allowedDistance
// and if it does add it to commonCharacters
for( $j= max( 0, $i-$allowedDistance ); $noMatch && $j < min( $i + $allowedDistance + 1, $str2_len ); $j++){
if( $temp_string2[$j] == $string1[$i] ){
$noMatch = False;

$commonCharacters .= $string1[$i];

$temp_string2[$j] = '';
}
}
}

return $commonCharacters;
}

function Jaro( $string1, $string2 ){

$str1_len = strlen( $string1 );
$str2_len = strlen( $string2 );

// theoretical distance
$distance = (int) floor(min( $str1_len, $str2_len ) / 2.0);

// get common characters
$commons1 = getCommonCharacters( $string1, $string2, $distance );
$commons2 = getCommonCharacters( $string2, $string1, $distance );

if( ($commons1_len = strlen( $commons1 )) == 0) return 0;
if( ($commons2_len = strlen( $commons2 )) == 0) return 0;

// calculate transpositions
$transpositions = 0;
$upperBound = min( $commons1_len, $commons2_len );
for( $i = 0; $i < $upperBound; $i++){
if( $commons1[$i] != $commons2[$i] ) $transpositions++;
}
$transpositions /= 2.0;

// return the Jaro distance
return ($commons1_len/($str1_len) + $commons2_len/($str2_len) + ($commons1_len - $transpositions)/($commons1_len)) / 3.0;

}

function getPrefixLength( $string1, $string2, $MINPREFIXLENGTH = 4 ){

$n = min( array( $MINPREFIXLENGTH, strlen($string1), strlen($string2) ) );

for($i = 0; $i < $n; $i++){
if( $string1[$i] != $string2[$i] ){
// return index of first occurrence of different characters
return $i;
}
}

// first n characters are the same
return $n;
}

function JaroWinkler($string1, $string2, $PREFIXSCALE = 0.1 ){

$JaroDistance = Jaro( $string1, $string2 );

$prefixLength = getPrefixLength( $string1, $string2 );

return $JaroDistance + $prefixLength * $PREFIXSCALE * (1.0 - $JaroDistance);
}