低效的Anagram解算器

时间:2015-05-12 16:30:07

标签: c++ algorithm anagram

以下程序基本上生成Anagram并继续解决它:

#include<iostream>
#include<fstream>
#include<algorithm>
#include<vector>
#include<string>
#include<time.h>
using namespace std;
int random(){
    int val = rand() % 26+1;
    return val;
}
void main(){
    srand(time(NULL));
    int b = 0, j = 0, x = 0; int count = 0;
    string line;
    vector<string>str;
    vector<string>chk;
    vector < int > v(8);
    vector <char> v1;
    vector <char > ::iterator p;
    vector <int > ::iterator p3;
    vector <char > ::iterator p2;
    while (b != 1){
        for (int i = 0; i < 8; i++){
            v[i] = random();
        }
    for (int i = 0; i < 8; i++){
        v1.push_back('a' + (v[i]-1));
        cout << v1[i]; 
    }
    string nam(v1.begin(), v1.end());
    sort(nam.begin(), nam.end());
    do {
        str.push_back(nam);
        count++;
    } while (next_permutation(nam.begin(),nam.end()));
    std::sort(v.begin(), v.end());
    char d = 'a'+v[7];//Comparision is case sensitive, so the letter should be lowercase//
    cout << endl;
    ifstream myfile("List of all words.txt");
    if (myfile.is_open())
    {
        while (getline(myfile, line))
        {
            if (line.find(d) == 0){
                /*cout << line << "\n"; */          
                break;
            }
            else{
                for (int i = 0; i < count; i++){
                    if (str[i].find(line) == 0){
                        cout << line << "\n";
                        break;
                    }
                }
            }
        }
        myfile.close();
    }
    cout << endl << count;

    cin >> b;
    }
}

我已经包含了一个包含英语单词列表的文件。现在我的问题是该程序有点太慢,特别是因为字典中的每个单词与大约40320个单词进行比较,具体取决于是否找到匹配项。所以,我想知道是否有人有任何关于如何使这个代码更有效,更省时的提示或建议。

1 个答案:

答案 0 :(得分:1)

您可以通过创建anagram字典来避免检查字典中的每个排列。它需要更多空间,但可以加速寻找解决方案。

更简单的替代方法是使用由每个单词的按字母顺序排序的字母组成的键来存储字典。你可以将候选人名单减少到最低限度。

这里有一步一步的施法

第一步:使用适应的数据结构

我建议您在 set 中加载文件,而不是每次按顺序浏览文件。

// load accepted words 
set<string>mydict;
ifstream myfile("List of all words.txt");
if(!myfile) {
    cerr << "Dictionnary file couldn't be loaded !\n";
    return 1;
}
istream_iterator<string> eof; 
istream_iterator<string> iit(myfile);
copy(iit, eof, inserter(mydict, mydict.begin())); // copy file to set
cout << mydict.size() << " words loaded\n"; 

第二步:调整算法

该集只被加载到内存中一次。因为它在O(log n)中使用了一种效率搜索算法,所以你已经经历了显着的性能提升。

while(b != 1)
{
    count = 0; 
    v.clear(); 
    for(int i = 0; i < 8; i++)   // construct random anagram
        v.push_back('a' + (random() - 1));
    string nam(v.begin(), v.end());
    cout << "Anagram:" << nam << endl; 
    std::sort(nam.begin(), nam.end());  // for using next permut()
    do {                 // check if any of the permutation is in the set
        if(mydict.find(nam) != mydict.end()) {
            cout << "Found:" << nam << endl;  // bingo !!!
            count++;
        }
    } while(next_permutation(nam.begin(), nam.end()));
    if(count == 0)
        cout << "Not found!"<<endl;

    cin >> b;
}

第三步:改进dictionaly数据结构

下一步是生成 map ,将字符串(字母排序的字谜字母)映射到匹配字词列表。基本上字母的字母是字的所有字谜的字谜。因此,相同键的所有单词都匹配相同的字谜。

// compute anagram map 
map<string, set<string>>myanadict;
for(auto x : mydict) {  // for every word in the dictionaly
    string alph=x; 
    sort(alph.begin(), alph.end());  // sort the letters  
    myanadict[alph].insert(x); 
}

最后一步:更新您的搜索以使用地图电源

现在好了,它变得紧张了

while(b != 1)
{
    count = 0; 
    v.clear(); 
    for(int i = 0; i < 8; i++) 
        v.push_back('a' + (random() - 1));
    string nam(v.begin(), v.end());
    //string nam = "dixeif";  // that was to test fixed values in my very smal file ;-)
    cout << "Anagram:" << nam << endl; 
    std::sort(nam.begin(), nam.end());  // sort now for the map search
    if (myanadict.find(nam)!=myanadict.end()) { // check if there's an entry
        cout << "Found:";    // bingo !!!
        copy(myanadict[nam].begin(), myanadict[nam].end(), ostream_iterator<string>(cout, " "));  // show all 
    }
    else cout << "Not found!"<<endl;