PHPで文字列類似度を計算する関数コード

4759 ワード

similar_text―2文字列の類似度int similar_を計算するtext(string$first,string$second[,float&$percent])$firstが必要です.比較する最初の文字列を指定します.$secondが必要です.比較する2番目の文字列を指定します.$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()関数は、主に2つの文字列の一致文字の数を計算するために使用されます.また、2つの文字列の類似度(パーセント)を計算することもできます.similarとtext()関数は、今日紹介するlevenshtein()関数よりも速いです.でも、similar_text()関数は、より少ない必要な変更回数でより正確な結果を提供することができる.速度を追求し精度が少なく,文字列長が限られている場合にlevenshtein()関数を用いることが考えられる.
説明を使用するには、マニュアルのlevenshtein()関数の説明を参照してください.
levenshtein()関数は、2つの文字列間のLevenshtein距離を返します.
Levenshtein距離は、編集距離とも呼ばれ、2つの文字列の間で、1つから別のものに変換するのに必要な最小限の編集操作回数を指す.許可された編集操作には、1つの文字を別の文字に置き換え、1つの文字を挿入し、1つの文字を削除することが含まれます.
たとえばkittenをsittingに変換します.
sitten (k→s)
sittin (e→i)
Sitting(→g)levenshtein()関数は、各操作(置換、挿入、削除)に同じ重みを与えます.ただし、オプションのinsert、replace、deleteパラメータを設定することで、各操作の代価を定義できます.
構文:
levenshtein(string1,string2,insert,replace,delete)
パラメータの説明
•string 1が必要です.比較する最初の文字列.
•string 2が必要です.比較する2番目の文字列.
•insertオプション.文字を挿入する代価.デフォルトは1です.
•replaceオプション.文字を置換する代価.デフォルトは1です.
•deleteオプション.文字を削除する代価.デフォルトは1です.
ヒントとコメント
•文字列の1つが255文字を超える場合、levenshtein()関数は-1を返します.
•levenshtein()関数は大文字と小文字に敏感ではありません.
•levenshtein()関数比similar_text()関数の方が速いです.でも、similar_text()関数は、より少ない修正が必要なより正確な結果を提供します.
 
  
echo levenshtein("Hello World","ello World");
echo "
";
echo levenshtein("Hello World","ello World",10,20,30);
?>

出力:1 30
補足は次のとおりです.
phpのデフォルトには関数similarがあります.text()は、文字列間の類似度を計算するために使用されます.この関数は、2つの文字列の類似度(パーセント)を計算することもできます.しかし、この関数は中国語の計算に不正確だと感じています.例えば、
 
  
echo similar_text(" 112 "," 112 ");

この2つのニュースタイトルは実は同じで、similarを使うとtext()類似ペアの結果は:42、すなわち42%しか似ていないので、この感覚は頼りにならない.今日ちょうどPHPコードを収集したのも、2つの文字列の類似度を比較するために使用され、直接コードを貼り付けた.

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で,明らかに正確であった.