mb_levenshtein

  • タグ:
  • タグはありません
<?php
/**
* 二つの文字列のレーベンシュタイン距離を計算する
*
* @param string $str1 最初の文字列
* @param string $str2 次の文字列
* @param string $encoding エンコーディング(= 内部エンコーディング)
* @return int レーベンシュタイン距離(OK) / -1(NG)
* @reference
* レーベンシュタイン距離(編集距離)をPHPで - 院生エンジニアのにっき
* http://life-hack.jp/blog/charly/157
* @cation
* 本家levenshteinの $cost_ins, $cost_rep, $cost_del には未対応
*/
function mb_levenshtein($str1, $str2, $encoding = NULL)
{
// エンコーディング省略
if ($encoding === NULL) {
// 内部エンコーディングを使用
$encoding = mb_internal_encoding();
}
 
$d = array ();
// 文字列を配列に変換
$ary1 = mbStrToAry($str1, $encoding);
$ary2 = mbStrToAry($str2, $encoding);
$len1 = count($ary1);
$len2 = count($ary2);
 
// 引数の文字列のうち、どちらかが255文字より大きい
if ($len1 > 255 || $len2 > 255) {
return -1;
}
 
for ($i1 = 0; $i1 <= $len1; $i1++) {
$d[$i1] = array ();
$d[$i1][0] = $i1;
}
 
for ($i2 = 0; $i2 <= $len2; $i2++) {
$d[0][$i2] = $i2;
}
 
for ($i1 = 1; $i1 <= $len1; $i1++) {
for ($i2 = 1; $i2 <= $len2; $i2++) {
$cost = ($ary1[$i1 - 1] == $ary2[$i2 - 1]) ? 0 : 1;
$d[$i1][$i2] = min(
$d[$i1 - 1][$i2    ] + 1, // 挿入
$d[$i1    ][$i2 - 1] + 1, // 削除
$d[$i1 - 1][$i2 - 1] + $cost // 置換
);
}
}
 
return $d[$len1][$len2];
}
 
/**
* マルチバイト文字列を1文字ずつ配列に格納する
*
* @param string $mbStr マルチバイト文字
* @param string $encoding エンコーディング
* @return array マルチバイト文字配列
* @reference
* - http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1417635014
*/
function mbStrToAry($mbStr, $encoding = NULL)
{
// エンコーディング省略
if ($encoding === NULL) {
// 内部エンコーディングを使用
$encoding = mb_internal_encoding();
}
 
$aryRet = array();
// 文字列長が0になるまでループ
while ($iLen = mb_strlen($mbStr, $encoding)) {
// 1文字目を配列に代入
$aryRet[] = mb_substr($mbStr, 0, 1, $encoding);
// 2文字目から末尾までを新しい文字列とする
$mbStr = mb_substr($mbStr, 1, $iLen, $encoding);
}
return $aryRet;
}
?>