我需要比较两个字符串并计算它们之间的相似度,以便筛选出最相似的字符串列表。
例如搜索“dog”将返回:
- dog
- doggone
- bog
- fog
- foggy
例如搜索“crack”将返回:
- crack
- wisecrack
- rack
- jack
- quack
我已经了解到以下算法:
还有哪些字符串相似性算法?
我需要比较两个字符串并计算它们之间的相似度,以便筛选出最相似的字符串列表。
例如搜索“dog”将返回:
例如搜索“crack”将返回:
我已经了解到以下算法:
还有哪些字符串相似性算法?
Levenshtein距离算法是我推荐的算法,它可以计算将一个字符串转换为另一个字符串所需的最小操作次数。操作次数越少表示这两个字符串越相似...
看起来您需要一种模糊匹配。这里是一些相似度评估度量的Java实现http://www.dcs.shef.ac.uk/~sam/stringmetrics.html。 这里有更详细的字符串相似度度量解释http://www.cs.cmu.edu/~wcohen/postscript/ijcai-ws-2003.pdf,具体取决于您实现的模糊程度和速度要求。
trie
结构的算法(可用于在文本中查找单词或帮助更正单词,但在您的情况下,您可以快速找到包含给定单词或除一个字母外的所有单词)。请先查看上面的维基百科链接。Tries 是最快的单词排序方法(n 个单词,搜索 s,创建 trie 的时间复杂度为 O(n),搜索 s 的时间复杂度为 O(1)(或者如果 a 是平均长度,则 trie 的时间复杂度为 O(an),搜索的时间复杂度为 O(s))。 1. c < a < R
2. a > c < R
3. > v < r < S
4. R > a > c
5. > v < S
6. v < a < r < S
7. S > r > a > v
c>i>v<a<R
找到)。为了容忍1个错误或缺失的字母进行搜索,您可以从s的每个字母开始迭代,并计算您从字典树中得到的连续的字母数-或通过跳过一个字母-。car
,
c
:在字典树中搜索c < a
和c < r
(s中的字母缺失)。要接受单词w中的错误字母,请尝试在每次迭代时跳过错误字母,以查看是否在其后面有ar
,这是O(w)的。对于两个字母,O(w²)等等......但是可以向字典树添加另一级索引,以考虑跳过字母-使字典树复杂化并贪婪地占用内存。a
,然后r
:与上述相同,但也可以反向搜索你可以这样做:
对于 haystack 中的每个 string 执行以下操作: offset := -1; matchedCharacters := 0; 对于 needle 中的每个 char 执行以下操作: offset := PositionInString(string, char, offset+1); 如果 offset = -1 那么 退出循环; 结束; matchedCharacters := matchedCharacters + 1; 结束; 如果 matchedCharacters > 0 那么 // 找到(部分)匹配 结束; 结束;
使用matchedCharacters可以确定匹配的“程度”。如果它等于needle的长度,则needle中的所有字符也都在string中。如果您还存储了第一个匹配字符的偏移量,那么您还可以通过从最后一个匹配字符的偏移量offset减去第一个匹配字符的偏移量来按匹配字符的“密度”对结果进行排序;差异越小,匹配越密集。
PositionInString
是什么意思? - Moritz Schmitz v. HülstPositionInString
是一个函数,它返回从 offset 开始的 string 中 char 的索引位置。 - Gumboclass Program {
static int ComputeLevenshteinDistance(string source, string target) {
if ((source == null) || (target == null)) return 0;
if ((source.Length == 0) || (target.Length == 0)) return 0;
if (source == target) return source.Length;
int sourceWordCount = source.Length;
int targetWordCount = target.Length;
int[,] distance = new int[sourceWordCount + 1, targetWordCount + 1];
// Step 2
for (int i = 0; i <= sourceWordCount; distance[i, 0] = i++);
for (int j = 0; j <= targetWordCount; distance[0, j] = j++);
for (int i = 1; i <= sourceWordCount; i++) {
for (int j = 1; j <= targetWordCount; j++) {
// Step 3
int cost = (target[j - 1] == source[i - 1]) ? 0 : 1;
// Step 4
distance[i, j] = Math.Min(Math.Min(distance[i - 1, j] + 1, distance[i, j - 1] + 1), distance[i - 1, j - 1] + cost);
}
}
return distance[sourceWordCount, targetWordCount];
}
static void Main(string[] args){
Console.WriteLine(ComputeLevenshteinDistance ("Stackoverflow","StuckOverflow"));
Console.ReadKey();
}
}