用于C ++的Anagram生成器(不使用STL)

时间:2011-07-04 04:21:14

标签: c++ string fstream anagram

我正在尝试使用非常基本的程序方法创建一个anagram解算器。我发现我可能应该使用类来完成这个,但是现在已经太晚了,我的任务即将到期。关于如何解决这个问题的任何建议都会很棒!

基本上,这就是算法应该做的事情:

  1. 获取字典中的所有单词;将它们存放在容器中
  2. 从用户那里得到一句话;如果合适,退出
  3. 获取用户输入的字词的所有排列
  4. 从排列中删除用户输入的字词
  5. 删除排列集合中不在第1部分中收集的字典中的所有单词
  6. 现在为了最后一步,我必须确保我不显示重复的字谜(即包含相同字母的字谜,例如“loop”)。我似乎无法使这个检查工作,这在下面的TODO注释块中有说明。

    任何建议都很棒!!

    #include <iostream>
    #include <fstream>
    #include <string>
    
    //
    // Change size below to accomodate more anagrams and dictionary words
    //
    #define MAX_ANGM_SIZE  4096
    #define MAX_WORD_SIZE  1048576
    
    using namespace std;
    
    
    //
    // Determines whether anagram is valid or not; will not display word
    // which user entered or words not contained in dictionary
    //
    bool isValidAnagram(string word, string userWord,
                    string dictionary[], unsigned int listIdx)
    {
        for(unsigned int idx = 0; idx < listIdx; ++idx)
        {
            if(word == userWord)
                return false;
            else if (word == dictionary[idx])
                return true;
        }
    
        return false;
    }
    
    
    //
    // Determines whether user's word is contained in the dictionary
    // or not
    //
    bool isValidWord(string word, string dictionary[], 
                 unsigned int listIdx)
    {
        for(unsigned int idx = 0; idx < listIdx; ++idx)
        {
            if(word == dictionary[idx])
                return true;
        }
    
        return false;
    }
    
    
    //
    // TODO:This function should test for duplicate anagrams and return
    // true if duplicates are found.
    //
    bool isRepeated(string anagrams[], unsigned int anaIdx)
    {
        for(unsigned int idx = anaIdx; idx != 0; --idx)
        {
            if(anagrams[idx] == anagrams[anaIdx])
                return true;
            else 
                return false;
        }
    
        return false;
    }
    
    
    //
    // Only display elements in array which aren't blank and don't 
    // display duplicate anagrams; notify user if no anagrams
    // were found.
    //
    void displayAnagrams(string anagrams[], unsigned int next)
    {
        int flag = 0;
    
        for (unsigned int idx = 0; idx < next; ++idx)
        {
    
            if((anagrams[idx] != "") || (!(isRepeated(anagrams, idx))))
            {
                if(idx == 1)
                    cout << "  Anagrams: ";
                if(idx > 0)
                    flag = 1;
    
                cout << anagrams[idx] << " ";
            }
            else 
                continue;
        }
    
        if(flag == 0)
            cout << "  no anagrams found" << endl;
    }
    
    
    static void swap(char &c1, char &c2)
    {
        char temp = c1;
    
        c1 = c2;
        c2 = temp;
    }
    
    
    //
    // Pass in word to be altered, the userWord for comparison, the array to store
    // anagrams, the dictionary for comparison, the count for the number of anagrams
    // and the count for number of dictionary words
    //
    static void permute(string word, string userWord, int k, string anagrams[],
                    string dictionary[], unsigned int &next, unsigned    int listIdx)
    {   
        if(k == word.length()-1)
        {
            if(isValidAnagram(word, userWord, dictionary, listIdx))
                anagrams[next] = word;
    
            ++next;
        }
        else
        {
            for(int idx = k; idx < word.length(); ++idx)
            {
                swap(word[k], word[idx]);
                permute(word, userWord, k+1, anagrams, dictionary, next, listIdx);
            }
        }
    }
    
    
    //
    // Create container to store anagrams, validate user's word in dictionary, get all
    // of the anagrams, then display all valid anagrams
    //
    void getAnagrams(string word, string dictionary[], unsigned int listIdx)
    {
        string anagrams[MAX_ANGM_SIZE];
        unsigned int next = 0;
    
        if(isValidWord(word, dictionary, listIdx))
        {
            permute(word, word, 0, anagrams, dictionary, next, listIdx);
        }
        else
        {
            cerr << "  \"" << word << "\"" << " is not a valid word" << endl;
            return;
        }
    
        displayAnagrams(anagrams, next);
    }
    
    
    //
    // Read in dictionary file, store contents of file in a list, prompt
    // the user to type in words to generate anagrams
    //
    int main()
    {
        string file;
        string word;
        string quit = "quit";
        string dictionary[MAX_WORD_SIZE];
    
        unsigned int idx = 0;
    
        cout << "Enter a dictionary file: ";
        cin  >> file;
        cout << "Reading file \"" << file << "\"" << endl;
        cout << endl;
    
        ifstream inFile(file.c_str());
    
            if(!(inFile.is_open())) 
        {
            cerr << "Can't open file \"" << file << "\""
             << endl;
    
            exit(EXIT_FAILURE);
        }
    
        while(!inFile.eof())
        {
            inFile >> dictionary[idx];
            ++idx;
        }
    
        inFile.close();
    
        while(true)
        {
            cout << "Enter a word: ";
            cin  >> word;
    
            if(word == quit) break;
    
            getAnagrams(word, dictionary, idx);
    
            cout << endl;
        }
    
        return 0;
    }
    

2 个答案:

答案 0 :(得分:2)

您可能想重新考虑您的步骤(3)。如果用户输入一个12个字母的单词,你就会有479,001,600个排列,这对于一次性组合可能是不切实际的(如果不是这样的话,那么一个16个字母的单词就会......)。

相反,尝试考虑如何存储单词并以不需要你这样做的方式查找潜在的字谜。

编辑:我得到解决大词的能力可能不是你现在最关心的问题,但是如果你通过组合有效词汇而不是从所有词开始,那么它实际上可能会使你的第四和第五步更容易可能性并删除所有不匹配的。从数组中删除一个项目有点尴尬,因为你必须将所有以下项目混乱以填补空白(这正是STL为你管理的那种事情)。

答案 1 :(得分:2)

更好的算法:不要存储你的单词,而是存储一个包含(你的单词,已排序的字母)的tupple。此外,您通过第二个键对该大存储进行排序(提示,您可以使用sqlite数据库为您完成工作并使用索引(不能是唯一的!)

E.g。存储

"Florent", "Abraham","Zoe"

你会存储在内存中

("aaabhmr", "abraham"),("eflnort","florent"),("eoz","zoe")

当你从用户那里得到你的话时,你只需使用相同的“内部字母排序”算法。

然后,您在存储中查找该模式,并且您可以非常快速地找到所有字谜(log(size of dictionary))。当然,原始单词是元组的第二个元素。

您可以使用类,标准结构,数据库,直到您选择最简单的实现(以及符合您要求的实现)