我有两个空格分隔的字符串......(X不代表相同的符号)
st1 = "abc def kok...."
st2 = "kok bbr def ffe ...."
我想构建一个交集字符串,如下所示:
common = "kok def"
在c ++中这样做的有效方法是什么?
由于
答案 0 :(得分:9)
我假设你已经tokenized your strings(this 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)
st1
并将它们全部放入std::set
st2
并检查每个子字符串是否存在于步骤1中创建的集合中。这将给出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::set
或std::multiset
(std::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;
}