C ++:如何构建两个空格分隔的字符串的交集字符串?

时间:2011-08-08 20:19:13

标签: c++ string stringstream

我有两个空格分隔的字符串......(X不代表相同的符号)

st1 = "abc def kok...."
st2 = "kok bbr def ffe ...."

我想构建一个交集字符串,如下所示: common = "kok def"

在c ++中这样做的有效方法是什么?

由于

3 个答案:

答案 0 :(得分:9)

使用std::set_intersection

示例程序:

我假设你已经tokenized your stringsthis solution似乎很容易实现)。

// Data
std::vector<string> a,b;
a.push_back("abc");b.push_back("kok");
a.push_back("def");b.push_back("bbr");
a.push_back("kok");b.push_back("def");
a.push_back("foo");b.push_back("ffe");

// Allocate space for intersection
std::vector<string> v(a.size()+b.size());

// Sort as required by set_intersection
std::sort(a.begin(),a.end());
std::sort(b.begin(),b.end());
// Compute
std::vector<string>::iterator it = std::set_intersection(a.begin(),a.end(),b.begin(),b.end(),v.begin());

// Display
v.erase(it,v.end());
for(std::vector<string>::iterator it = v.begin();it < v.end(); ++it) std::cout<<*it<<std::endl;

复杂性应该是令牌(或子串)数量的 O(n log n)

答案 1 :(得分:2)

  1. 在子字符串中拆分st1并将它们全部放入std::set
  2. 在子字符串中拆分st2并检查每个子字符串是否存在于步骤1中创建的集合中。
  3. 这将给出O(n log n)执行时间。你必须完全遍历两个字符串。对于每个元素,从集合中插入和检索通常为O(log n),这会得到O(n log n)

    如果您可以使用基于散列的集合(或其他一些无序集合),O(1)插入和检索复杂性,则会将复杂性降低到O(n)

答案 2 :(得分:1)

为了扩大您已经获得的答案,基本上有两个因素需要考虑,您没有指定。首先,如果输入中存在重复元素,您是否需要考虑输出的元素。例如,给定输入如:

st1 = "kok abc def kok...."
st2 = "kok bbr kok def ffe ...."

由于“kok”在两个输入中出现两次,“kok”应该在输出中出现一次还是两次?

第二个是你的使用模式。你有一个读取所有输入的模式,然后生成一个输出,或者是一个更迭代,你可能会读取一些输入,生成一个输出,读取更多输入,添加到前一个,生成另一个输出,等等上?

如果您要阅读所有输入,然后生成一个输出,您可能希望使用std::vector后跟std::sort。如果您只希望每个输入在输出中只出现一次,无论它在两个输入中出现的频率如何,那么您将按照std::unique进行操作,最后执行set_intersection

如果您想支持迭代更新,那么您可能希望使用std::setstd::multisetstd::set使每个输出唯一,std::multiset如果重复输入应该给出重复的结果)。

编辑:基于输入中缺少重复,一个非常快速的简单实现将是这样的:

#include <string>
#include <set>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <iostream>

int main() {   
    std::string st1("abc def kok");
    std::string st2("kok bbr def ffe");

    std::istringstream s1(st1);
    std::istringstream s2(st2);

    // Initialize stringstreams. Whine about most vexing parse.
    std::set<std::string> words1((std::istream_iterator<std::string>(s1)), 
                                 std::istream_iterator<std::string>());

    std::set<std::string> words2((std::istream_iterator<std::string>(s2)), 
                                 std::istream_iterator<std::string>());

    std::ostringstream common;

    // put the intersection into common:
    std::set_intersection(words1.begin(), words1.end(), 
                          words2.begin(), words2.end(),
                          std::ostream_iterator<std::string>(common, " "));

    std::cout << common.str();  // show the result.
    return 0;
}