来自OCR的单词并需要一个紧密匹配的列表。 可以没有maxFrom。 示例代码是强力的,但希望它定义了要求。 对于600,000的名单,这需要2秒。 FTSword.Word是一个字符串。
理想情况下,“找到”只会给第二个d带来额外的功劳。一旦它找到了我,那么f就没有信用。蛮力我能做到这一点。我希望减少2秒钟。将测试并报告任何提议的解决方案。
问题??是。如何让它更快? (而且更聪明)
由于
char[] find = new char[] { 'f', 'i', 'n', 'd' };
char[] word;
int maxFrom = 10;
int minMatch = 3;
int count;
List<FTSword> matchWords = new List<FTSword>();
foreach (FTSword ftsw in fTSwords)
{
if (ftsw.Word.Length < maxFrom)
{
word = ftsw.Word.ToCharArray();
count = 0;
foreach (char fc in find)
{
foreach (char wc in word)
{
if (char.ToLower(wc) == char.ToLower(fc))
{
count++;
break;
}
}
}
if (count >= minMatch)
{
// Debug.WriteLine(count.ToString() + ftsw.Word);
matchWords.Add(ftsw);
}
}
}
Debug.WriteLine(matchWords.Count.ToString());
答案 0 :(得分:1)
您的核心算法目前是O(n ^ 2),因为您有两个嵌套循环来查找匹配的字符。您可以使用包含find
字符串中每个字符的字符数的字典轻松地创建该部分O(n):
string find = "find";
var findMap = new Dictionary<char, int>();
foreach (char c in find)
{
if (findMap.ContainsKey(c))
{
findMap[c] = findMap[c] + 1;
}
else
findMap.Add(c, 1);
}
//findMap is pre-generated once
string word = "pint";
int count = 0;
//runs for each word in list, now in O(n)
foreach(char c in word)
{
int charCount;
if(findMap.TryGetValue(c, out charCount))
{
if(charCount > 0)
{
charCount--;
findMap[c] = charCount;
count++;
}
}
}
答案 1 :(得分:1)
如果你确定在开始之前它是低位的,你可以删除fc上的char.ToLower()
。
您也可以尝试使用IndexOf()
查找第一个(然后是后续出现的字符),因为BCL实现可能在内部比您自己的循环管理更快。
您也可以尝试反向运行循环,这可以提供加速:
for (int i = arr.Length - 1; i >= 0; i--)
但实际上,对于OCR,为什么要总结字符串中任意位置的匹配字符,而不是像Damerau-Levenshtein那样进行真正的编辑距离?