C ++在单词中查找字谜

时间:2013-09-16 17:44:30

标签: c++ string algorithm logic

我正在研究一个程序,该程序使用std:count查看某个特定单词是否是一个字谜但是,我不认为我的函数逻辑是正确的,我似乎无法弄明白。

假设文件中有以下字词:

Evil
Vile
Veil  
Live

我的代码如下:

#include <iostream>
#include <vector>
#include <fstream>
#include <map>
using namespace std;

struct Compare {
std::string str;
Compare(const std::string& str) : str(str) {}
};

bool operator==(const std::pair<int, std::string>&p, const Compare& c) {
return c.str == p.second;
}
   bool operator==(const Compare& c, const std::pair<int, std::string>&p) {
   return c.str == p.second;
}

std::vector<std::string> readInput(ifstream& file)
{
std::vector<std::string> temp;

string word;

while (file >> word)
{
    temp.push_back(word);
}
std::sort(temp.begin(), temp.end());

return temp;
}

int main(int argc, char *argv[]) {  

string file = "testing.txt";
ifstream ss(file.c_str());

if(!ss.is_open())
{
    cerr << "Cannot open the text file";
}

std::vector<std::string> words = readInput(ss);

std::map<int, std::string> wordsMap; 

//std::map<std::string value, int key> values; 

for(unsigned i=0; (i < words.size()); i++)
{
    wordsMap[i] = words[i];
}


int count = std::count(wordsMap.begin(), wordsMap.end(), Compare("Evil"));
cout << count << endl;
}

我很确定这只是我的逻辑错误的一个例子。我希望有人可以提供帮助:)

5 个答案:

答案 0 :(得分:2)

最简单的方法是

检查如下(伪代码)

bool isAnagram(string s, string t) {return sort(s) == sort(t); }

所以,使用一些思考如下,不需要std::map

struct Compare {
std::string str;
Compare(const std::string& x) : str(x) { 
    std::sort(str.begin(),str.end()); std::transform(str.begin(), 
    str.end(),str.begin(), ::toupper);}

    bool operator ()(const std::string& t)
    {
        std::string s= t;
        std::transform(s.begin(), s.end(),s.begin(), ::toupper);
        std::sort(s.begin(),s.end());

    return s == str;
    }
};

然后

int count = std::count_if(words.begin(), words.end(), Compare("Evil"));

参见 HERE

答案 1 :(得分:1)

编辑:在你现在的代码中,你正在检查字符串是否完全相同(不是字谜)。

来代替:
对于每个单词,创建一个包含26个元素的数组,每个元素对应一个字母的字母。逐个字符地解析每个单词,并增加相应数组中特定字符的计数。

例如对于邪恶,数组将是:

0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0. // It has 1's for letters e,v,i and l
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z

您为每个单词创建此数组。在您的情况下,所有单词将具有相同的数组。然后,您可以逐个元素地比较这些数组,并相应地进行。

现在您只需要查看哪些单词具有相同的对应数组。

如果要成对地比较所有N个单词,可以使用O(N ^ 2)复杂度中的两个嵌套循环。 比较一对的复杂度是O(1) 创建数组的复杂性= O(L)其中L是字符串的长度。

答案 2 :(得分:1)

这不是最有效的算法,但可以快速更改您的程序:

bool operator==(const std::pair<int, std::string>&p, const Compare& c) {
  std::string a = c.str;
  std::transform(a.begin(), a.end(), a.begin(), ::tolower);
  std::sort(a.begin(), a.end());

  std::string b = p.second;
  std::transform(b.begin(), b.end(), b.begin(), ::tolower);
  std::sort(b.begin(), b.end());

  return a == b;
}

答案 3 :(得分:0)

请考虑以下事项:

map<string, set<string>> anagrams;

for (auto word : words)
    anagrams[sort(word)].insert(word);

const set<string>& find_anagrams(const string& word)
{
    return anagrams[word];
}

答案 4 :(得分:0)

如果你有很多相对较短的单词(或者你可以使用大量的lib),那么你可以使用类似于我在这里写的解决方案 -

Generate same unique hash code for all anagrams

基本上 - 将每个字符映射到一个唯一的素数(不一定要大,你可以将整个ABC映射到最多101个素数),并且每个单词乘以从它接收的素数字符。由于乘法是可交换的,因此anagrams会给出相同的结果,所以你只需比较那个结果,哈希它,或做你想做的任何事情

请记住,对于长词,值会增长得非常快,因此您可能需要一个大数字库