0

非常に基本的な手続き型アプローチを使用して、アナグラム ソルバーを作成しようとしています。おそらくクラスを使用してこれを行うべきだったことがわかりましたが、今では遅すぎて、割り当ての期限が近づいています。これを理解する方法についての提案は素晴らしいでしょう!

基本的に、これはアルゴリズムが行うべきことです。

  1. 辞書内のすべての単語を取得します。それらをコンテナに保管する
  2. ユーザーから言葉をもらいます。必要に応じて終了
  3. ユーザーが入力した単語の順列をすべて取得します
  4. ユーザーが入力した単語を順列から取り除きます
  5. パート 1 で収集した辞書にも含まれていない順列コレクションのすべての単語を削除します

最後のステップとして、重複したアナグラム (つまり、「ループ」などの同じ文字を含むアナグラム) を表示しないようにする必要があります。このチェックを機能させることができないようです。これは、以下の 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;
}
4

2 に答える 2

2

より良いアルゴリズム: 単語を保存するのではなく、(単語、ソートされた文字) を含むタプルを保存します。さらに、その大きなストレージを2番目のキーでソートします(ヒント、sqliteデータベースを使用して作業を行い、インデックスを使用できます(一意にすることはできません!))

保存する例

"Florent", "Abraham","Zoe"

あなたはメモリに保存します

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

ユーザーから単語を取得したら、同じ「単語内の文字の並べ替え」アルゴリズムを使用するだけです。

次に、ストレージでそのパターンを探すと、log(size of dictionary)ソートされているため、すべてのアナグラムが非常に迅速に見つかります ( )。もちろん、元の単語はタプルの 2 番目の要素です。

クラス、標準構造、データベースを使用して、最も簡単な実装 (および要件に合った実装) を選択できます。

于 2011-07-04T05:07:11.320 に答える
2

ステップ (3) を再考することをお勧めします。ユーザーが 12 文字の単語を入力すると、479,001,600 の順列があり、一度にすべてを組み立てるのはおそらく非現実的です (そうでない場合、16 文字の単語は...)。

代わりに、それを必要としない方法で単語を保存し、潜在的なアナグラムを検索する方法を考えてみてください.

編集: 大きな単語を解決する能力は、現時点では最大の関心事ではないかもしれませんが、すべての可能性から始めて削除するのではなく、有効な単語のセットを組み立てることによって、4 番目と 5 番目のステップを実際に簡単にすることができます。一致しないすべてのもの。配列からアイテムを「削除」するのは、ギャップを埋めるために次のすべてのアイテムをシャッフルする必要があるため、少し厄介です (これはまさに STL が管理する種類のものです)。

于 2011-07-04T04:36:17.007 に答える