<?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; } ?>