如何在std :: string的两个向量之间找到常用词

时间:2013-07-26 05:15:56

标签: c++ stl functor

我试图找到两个std :: string向量之间的常用词。我希望将它们放入按长度排序的排序列表中,然后按字母顺序对每个长度的单词进行排序。我需要使用stl函数和函子。

我的想法: 使用for_each遍历第一个向量,对于每个单词,使用仿函数将其与另一个向量进行比较(如果常见,则附加到仿函数中的列表)。然后结果列表中只有常用的单词。这是我被卡住的地方,我知道如何按字母顺序排序,但我如何按长度排序,然后按字母顺序排序相同长度的块?我环顾四周,但我找不到我需要的东西。或者,我只是想错了方法。有什么想法吗?

示例:

vec1:“和”,“因此”,“它”,“有”,“一个”,“开头”,“和”,“结束”

vec2:“和”,因此“,”星星“,”是“,”开始“,”到“,”堕落“,”到“,”他们的“,”结束“

结果:“和”,“结束”,“开始”

5 个答案:

答案 0 :(得分:3)

如果您允许对vec1vec2进行排序,则可以使用std::set_intersection根据您指定的条件对向量进行排序,并获取按相同条件排序的公共元素:

#include <algorithm>
#include <iterator>

std::sort(vec1.begin(), vec1.end(), funny_comp);
std::sort(vec2.begin(), vec2.end(), funny_comp);
std::list<std::string> intersection;

std::set_intersection(vec1.begin(), vec1.end(),
                      vec2.begin(), vec2.end(),
                      std::back_inserter(intersection),
                      funny_comp);

其中funny_comp按字符串长度进行比较,如果字符串具有相同的长度,则执行字符串的字典比较:

bool funny_comp(const std::string &lhs, const std::string &rhs)
{ 
   return (lhs.size()) == rhs.size()) ? lhs < rhs
                                      : lhs.size() < rhs.size();
}

请参阅working demo here

答案 1 :(得分:1)

如果向量已排序,您可以使用std :: set_intersection()来查找每个向量的共同词。 std :: set_intersection()是项目数量的O(N)时间。当然排序是O(N log N)。

答案 2 :(得分:1)

您的解决方案是O(n ^ 2)。这意味着如果向量的长度为n,则执行n * n次操作:遍历一个向量,对于每个元素,遍历另一个向量以查找它。

如果你可以对向量进行排序(使用sort函数。不需要像你提到的那样花哨的排序),时间是O(n)。使用set_intersection。即使您无法对它们进行排序 - 将它们复制到新的向量中并对这些新向量进行排序。它比你提出的要快得多。

答案 3 :(得分:1)

要按长度排序,那么在词汇上,你需要定义一个比较函数(或仿函数)来做到这一点:

struct by_len_lex { 
   bool operator()(std::string const &a, std::string const &b) { 
       if (a.length() < b.length())
           return true;
       if (a.length() > b.length())
           return false;
       return a < b;
    }
};

// ...
std::sort(strings1.begin(), strings1.end(), by_len_lex());
std::sort(strings2.begin(), strings2.end(), by_len_lex());

// find intersection:
std::set_intersection(strings1.begin(), strings1.end(), 
                      strings2.begin(), strings2.end(),
                      std::back_inserter(results),
                      by_len_lex());

请注意,由于您要定义排序条件,因此在进行交叉时排序时需要指定相同的条件。

答案 4 :(得分:0)

这可能不是最佳解决方案,但可以使用以下地图:

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

int main()
{
vector <string> v1{"and", "thus", "it", "has", 
                  "a", "beginning", "and", "end"};

vector <string> v2{"and" ,"therefore", "stars", 
                   "are", "beginning", "to","fall","to",
                   "their", "end"};

map <string,int> m;

auto check=[&](const string& x) { return m.find(x) != m.end() ; } ;

for_each(v1.begin(),
         v1.end(),
         [&](const string& x){ 
                m[x] =1;
            } 
         );

for_each(v2.begin(),
         v2.end(),
         [&](const string& x){ 
            if(check(x)) 
                cout<<x<<endl;
            } 
         );

}