C++ 如何在std::string的两个向量之间查找公共词

C++ 如何在std::string的两个向量之间查找公共词,c++,stl,functor,C++,Stl,Functor,我试图在std::string的两个向量之间找到常用词。我想把它们放到一个按长度排序的列表中,然后每个长度的单词按字母顺序排序。我需要使用stl函数和函子 我的想法: 使用for_遍历第一个向量,对于每个单词,使用functor将其与另一个向量进行比较(如果通用,则附加到functor中的列表)。然后,生成的列表中只有常用词。这就是我被卡住的地方,我知道如何按字母顺序排序,但我如何按长度排序,然后按字母顺序排序相同长度的块?我已经环顾了stl,但我没有找到我需要的。或者,我只是想错了。有什么想法

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

我的想法: 使用for_遍历第一个向量,对于每个单词,使用functor将其与另一个向量进行比较(如果通用,则附加到functor中的列表)。然后,生成的列表中只有常用词。这就是我被卡住的地方,我知道如何按字母顺序排序,但我如何按长度排序,然后按字母顺序排序相同长度的块?我已经环顾了stl,但我没有找到我需要的。或者,我只是想错了。有什么想法吗

例如:

因此,它有,开始,和结束

vec2:因此,星星是,开始、结束、坠落、结束


结果:和、结束、开始

如果向量已排序,则可以使用std::set_intersection查找每个向量的公用词。std::设置交叉点的项目数是否准时。当然,排序在日志N上。

如果向量已排序,则可以使用std::set_intersection查找每个向量共有的单词。std::设置交叉点的项目数是否准时。当然,排序在日志N上。

如果允许您对vec1和vec2进行排序,您可以使用来根据指定的标准对向量进行排序,并获得公共元素,按相同的标准排序:

#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);

请参阅。

如果允许对vec1和vec2进行排序,则可以使用来根据指定的标准对向量进行排序,并获得按相同标准排序的公共元素:

#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);

请参阅。

您的解决方案位于^2上。这意味着,如果向量的长度为n,那么您将执行n*n操作:遍历一个向量,对于每个元素,遍历另一个向量以查找它


如果可以使用sort函数对向量进行排序。不需要像你提到的那样花哨,时间到了。使用集合交叉。即使你不能对它们进行排序,也要将它们复制到新的向量中,并对这些新向量进行排序。它比您的建议快得多。

您的解决方案在^2上。这意味着,如果向量的长度为n,那么您将执行n*n操作:遍历一个向量,对于每个元素,遍历另一个向量以查找它


如果可以使用sort函数对向量进行排序。不需要像你提到的那样花哨,时间到了。使用集合交叉。即使你不能对它们进行排序,也要将它们复制到新的向量中,并对这些新向量进行排序。它比您建议的要快得多。

要按长度排序,然后按词汇进行排序,您需要定义一个比较函数或函子:

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());

请注意,由于您正在定义排序标准,因此在排序和进行交叉时都需要指定相同的标准。

要按长度排序,然后按词汇进行排序,需要定义一个比较函数或函子:

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());

请注意,由于您正在定义排序标准,因此在排序和进行交叉时都需要指定相同的标准。

这可能不是最佳解决方案,但可以使用如下映射:

#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;
            } 
         );

}

这可能不是最好的解决方案,但可以使用如下映射:

#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;
            } 
         );

}


你能先排序向量吗?是的,如果我创建一个eachI道歉的副本,我忘了提到我不能在结果向量中有重复的单词。你能先排序向量吗?是的,如果我创建一个eachI道歉的副本,我忘了提到我不能在结果向量中有重复的单词。是的,但是它创建了一堆重复项,所以我在你的算法中添加了std::unique,这样会不会更复杂?@MarinaGolubtsova:如果原始输入中有重复项,这将在输出中保留它们。如果你想消除它们,你可以使用std::unique来消除它们。这样做了,但它会创建一堆重复的sok,所以我在你的算法中添加了std::unique,这样会不会更复杂?@MarinaGolubtsova:如果你在原始输入中有重复的,这将在输出中保留它们。如果你想消除它们,你可以使用std::unique来消除它们。没有向量没有排序,但是ONlogN的复杂度仍然比我没有排序的好。没有向量没有排序,但是ONlogN的复杂度仍然比我的好。有没有避免重复的方法?@maringolubtsova除非我误解了你,这个解决方案会删除重复的。请看演示。有没有避免重复的方法?@MarinaGolubtsova除非我误解了你的意思,否则此解决方案会删除重复的内容。看演示。你说如果你能排序,时间是开着的,不是在日志n上排序吗?你说如果你能排序,时间是开着的,不是在日志n上排序吗?