92 lines
2.1 KiB
Go
92 lines
2.1 KiB
Go
package bastion_init
|
||
|
||
import "strings"
|
||
|
||
// 假设我们的预定义字符串列表存储在这个map中,键为字符串索引,值为字符串本身
|
||
var dictionary = map[string]struct{}{
|
||
"apple": {},
|
||
"apply": {},
|
||
"apron": {},
|
||
"docker": {},
|
||
"docker-compose": {},
|
||
"harbor": {},
|
||
// ...其他词汇
|
||
}
|
||
|
||
// normalize 将字符串转换为小写并去除特殊符号
|
||
func normalize(s string) string {
|
||
return strings.ToLower(strings.ReplaceAll(s, "\\W", ""))
|
||
}
|
||
|
||
// findBestMatch 在字典中找到最合适的单词
|
||
func findBestMatch(query string) string {
|
||
normQuery := normalize(query)
|
||
|
||
// 将查询字符串排序,以便二分查找
|
||
sortedQuery := []rune(normQuery)
|
||
|
||
var bestMatch string
|
||
minDistance := len(dictionary) + 1 // 最初假设没有匹配项
|
||
|
||
// 遍历字典中的所有单词
|
||
for word, _ := range dictionary {
|
||
normWord := normalize(word)
|
||
distance := levenshteinDistance(sortedQuery, []rune(normWord)) // 计算编辑距离
|
||
|
||
// 如果当前单词的编辑距离小于等于最佳匹配的距离,并且它是第一个匹配项(或者距离相同但字典序更低)
|
||
if distance <= minDistance || (distance == minDistance && strings.ToLower(word) < normQuery) {
|
||
minDistance = distance
|
||
bestMatch = word
|
||
}
|
||
}
|
||
|
||
return bestMatch
|
||
}
|
||
|
||
// levenshteinDistance 计算两个字符串之间的编辑距离(插入、删除或替换一个字符的次数)
|
||
func levenshteinDistance(a, b []rune) int {
|
||
lenA := len(a)
|
||
lenB := len(b)
|
||
|
||
dist := make([][]int, lenA+1)
|
||
for i := range dist {
|
||
dist[i] = make([]int, lenB+1)
|
||
}
|
||
|
||
for i := 0; i <= lenA; i++ {
|
||
dist[i][0] = i
|
||
}
|
||
for j := 0; j <= lenB; j++ {
|
||
dist[0][j] = j
|
||
}
|
||
|
||
for i := 1; i <= lenA; i++ {
|
||
for j := 1; j <= lenB; j++ {
|
||
cost := int(a[i-1] - b[j-1])
|
||
dist[i][j] = minInt(dist[i-1][j]+1, dist[i][j-1]+1, dist[i-1][j-1]+cost)
|
||
}
|
||
}
|
||
|
||
return dist[lenA][lenB]
|
||
}
|
||
|
||
// minInt 找到三个整数中的最小值
|
||
func minInt(a, b, c int) int {
|
||
if a < b {
|
||
if a < c {
|
||
return a
|
||
}
|
||
return c
|
||
}
|
||
if b < c {
|
||
return b
|
||
}
|
||
return c
|
||
}
|
||
|
||
func main() {
|
||
query := "app!"
|
||
bestMatch := findBestMatch(query)
|
||
println("The best match for", query, "is:", bestMatch)
|
||
}
|