function closest_word(string $input, array $words): string {
$shortest = -1;
$closest = '';
foreach ($words as $word) {
$lev = levenshtein($input, $word);
if ($lev === 0) {
return $word; // 完全匹配
}
if ($lev <= $shortest || $shortest < 0) {
$closest = $word;
$shortest = $lev;
}
}
return $closest;
}
$states = [
'AL' => 'Alabama', 'AK' => 'Alaska', 'AZ' => 'Arizona',
'CA' => 'California', 'NY' => 'New York', 'TX' => 'Texas',
// ... 完整 50 州
];
$input = 'Wiscsin'; // 用戶輸入錯誤
$corrected = closest_word($input, array_values($states));
echo $corrected; // Wisconsin
計算將字串 A 轉換為字串 B 所需的最少單字元編輯操作次數(插入、刪除、替換)。動態規劃實現,時間複雜度 O(m×n)。
// 基本用法
levenshtein($str1, $str2);
// 自定義成本 (插入、替換、刪除)
levenshtein($str1, $str2, $costIns, $costRep, $costDel);
// 限制最大距離 (超過回傳 -1,效能優化)
levenshtein($str1, $str2, 1, 1, 1, $maxDistance);
function searchSuggestions(string $query, array $dictionary, int $limit = 5): array {
$results = [];
foreach ($dictionary as $word) {
$dist = levenshtein($query, $word, 1, 1, 1, 3); // 只找編輯距離 ≤ 3
if ($dist !== -1) {
$results[$word] = $dist;
}
}
asort($results);
return array_slice(array_keys($results), 0, $limit);
}
function mergeSimilarKeywords(array $keywords, int $threshold = 2): array {
$merged = [];
foreach ($keywords as $kw) {
$found = false;
foreach ($merged as $existing) {
if (levenshtein($kw, $existing) <= $threshold) {
$found = true; break;
}
}
if (!$found) $merged[] = $kw;
}
return $merged;
}
Levenshtein 基於字元,中文需先分詞 (jieba-php) 再計算詞級距離,或使用專門的中文相似度庫。
abs(strlen($a) - strlen($b)) > $threshold 直接跳過| 演算法 | 特點 | 適用場景 |
|---|---|---|
| Levenshtein | 標準編輯距離 | 通用、短字串 |
| Damerau-Levenshtein | 支援相鄰字元交換 | 鍵盤輸入錯誤修正 |
| Jaro-Winkler | 前綴加權、適合人名 | 姓名/地址匹配 |
| 余弦相似度 (TF-IDF) | 語義級、需向量化 | 長文本、搜尋引擎 |