优化处理字谜的算法

时间:2015-05-30 09:11:16

标签: c++ algorithm

我正在研究一个项目,在某些时候,我需要接受信件,然后搜索我所拥有的单词词典,并输出我所接受的字母的字母可以找到的字典中的所有单词。

例如,如果我接受字母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);
    }

谢谢。

1 个答案:

答案 0 :(得分:3)

C ++标准库已经具有您正在实施的结构(例如set,或使用lower_boundvector)和算法(next_permutation);使用这些可能比编写自己的解决方案更有效。

但正如你所说,阶乘增长非常快:你需要的是一种新的算法。这里有一个标准技巧:两个字符串是彼此的字谜,当且仅当它们排序后它们是相同的。例如,排序doggod都会给dgo

通过使用排序版本,您可以完全避免迭代排列。 (在实施这些方法时,了解multimap可能有所帮助)

(另一种方法是使用multiset个字符;同样,multiset {d,o,g}和{g,o,d}比较相等。但排序后的字符串会更有效率用)