我正在寻找一种改进我目前拥有的算法的方法,尽管它可以工作,但目前具有O(n ^ 2)的复杂度。我希望尽可能降低这种复杂性,或者改善/更改算法本身以提高运行时间。
我有一个字符串列表,每个字符串包含多个单词,最终目标是找到这些字符串之间的“匹配项”,并根据百分比“相似度”进行排序。
假设我有以下字符串:
“世界尽头”
“旅程的开始”
“时间的尽头”
“今天我们离开这个世界的时间”
我的算法执行以下步骤:
最终,我剩下了成对的字符串(开始列表中所有字符串的所有可能配对)以及它们之间匹配的百分比值。然后,我可以丢弃所有低于某个阈值的那些匹配项,并且仅使用那些高于阈值的匹配项。该阈值是用户定义的,整个算法用作“过滤”非常大的一组数据的方法,从而使人眼只能处理最初看起来非常匹配的那些数据。
您可以从算法的嵌套循环(即O(n ^ 2))部分中想象到,这非常慢,并且随着输入大小的增加而变得相当慢。
是否有任何方法可以改进此算法的Big O或对算法产生相同的输出以提高运行时复杂性进行任何更改?
答案 0 :(得分:0)
如果在所有计算中都随身携带字符串,则会带来额外的复杂性,这使得最后一个操作不是O(M ^ 2)而是O(M ^ 2 * sizeof(句子)* AvgLength(word))< / p>
让我们看看(概念代码)
std::vector<std::set<int>> sSets;
sentenceSets.reserve(sentences.size());
for(auto& sentence : sentences) { // O(m)
std::vector<const char *> words = SplitWord(sentence); // O(n) needs to go through all letters.
sSet.emplace_back();
for(auto& word: words) {
int wordNo = LookUp(word); // table of all words, with entries of 0 for unwanted words. O(log AllWords)
if (wordNo)
sSet.back().insert(wordNo); // also removes duplicates. O(Log(#diff words in sentence))
}
}
如果您认为所有可能单词的哈希表都能正常工作,则总计O(m Log(AllWords)avgWordLen)或O(m crashFactor avgWordLen)。
LookUp
为以后的所有比较保存了因子O(字中的字母)。
for(const auto& theSet : sSet) { // O(sSet.size()
for(const auto& cmpSet : sSet) { // O(sSet.size()
std::vector<int> intersect;
std::set_intersection(theSet.begin(), theSet.end(),
cmpSet.begin(), cmpSet.end(),
std::back_insert<std::vector<int>>(intersect)); // O(set.size())
StoreRes(theSet, cmpSet, intersect);
}
}
这里总共是O(sSet.size()^ 2 * O(set.size())。 可以优化为只运行O(sSet.size()* sSet.size()/ 2),因为表是对称的。
使用LookUp
在这里节省了因子O(字长)。
为了更快地进行实际操作,可以将std :: set替换为flat_set。