我正在研究一个项目,在某些时候,我需要接受信件,然后搜索我所拥有的单词词典,并输出我所接受的字母的字母可以找到的字典中的所有单词。
例如,如果我接受字母odg 该程序将从字典中找到单词dog and god。 我面临的问题是,如果我接受更多的字母,程序将永远输出。我有点理解为什么,因为字谜基本上是给定字母的阶乘,而且这种增长超快。我想知道我是否可以修改我已编写的代码以使该程序更快。
我将在这里发布3个功能,这是可怕的减速发生的地方。请注意,我的字典存储在二叉搜索树中。
//lookup accepts the letters, which will be rearrange and searched in the BST
//it accepts function pointer callback, but do not worry about it, its just the //way to output the words that I found.
void DictionaryImpl::lookup(string letters, void callback(string)) const
{
if (callback == nullptr)
return;
removeNonLetters(letters);
if (letters.empty())
return;
string permutation = letters;
string tempString;
do
{
tempString=findValue(root, permutation);
if(tempString !="!!!ValueNotFound!!!")
callback(tempString);
generateNextPermutation(permutation);
} while (permutation != letters);
}
//findValue accepts pointer to the root of the tree
//and it accepts the string that it is searching
string DictionaryImpl::findValue(Node* p, string searchValue) const
{
if(p !=nullptr)
{
if(p ->data == searchValue)
return searchValue;
else if(p->data > searchValue)
return findValue(p->left,searchValue);
else if(p->data < searchValue)
return findValue(p->right,searchValue);
}
return "!!!ValueNotFound!!!";
}
//accepts a string that it is going to rearrange
void generateNextPermutation(string& permutation)
{
string::iterator last = permutation.end() - 1;
string::iterator p;
for (p = last; p != permutation.begin() && *p <= *(p-1); p--)
;
if (p != permutation.begin())
{
string::iterator q;
for (q = p+1; q <= last && *q > *(p-1); q++)
;
swap(*(p-1), *(q-1));
}
for ( ; p < last; p++, last--)
swap(*p, *last);
}
谢谢。
答案 0 :(得分:3)
C ++标准库已经具有您正在实施的结构(例如set
,或使用lower_bound
和vector
)和算法(next_permutation
);使用这些可能比编写自己的解决方案更有效。
但正如你所说,阶乘增长非常快:你需要的是一种新的算法。这里有一个标准技巧:两个字符串是彼此的字谜,当且仅当它们排序后它们是相同的。例如,排序dog
和god
都会给dgo
。
通过使用排序版本,您可以完全避免迭代排列。 (在实施这些方法时,了解multimap
可能有所帮助)
(另一种方法是使用multiset
个字符;同样,multiset {d,o,g}和{g,o,d}比较相等。但排序后的字符串会更有效率用)