std::set_intersection求字符交集需先将字符串转为有序无重容器(如std::set),再调用算法,结果为每个公共字符一次;若需保留重复次数,则应改用unordered_map统计频次后取最小值。

用 std::set_intersection 提取公共字符(需先排序)
直接对两个字符串求“相同字符”,本质是求字符集合的交集,但 std::set_intersection 要求输入已排序且去重——所以得先转成 std::set 或手动排序去重。它不保留重复次数,只返回每个公共字符一次。
- 如果原字符串含重复字符(如
"aabb"和"abcc"),结果只有'a','b',不是'a','a','b','b' - 操作步骤:转
std::string→std::vector<char></char>→ 排序 +std::unique→ 传给set_intersection - 更简单做法:用两个
std::set<char></char>构造后取交集,代码短且语义清晰
std::string s1 = "hello", s2 = "world";
std::set<char> set1(s1.begin(), s1.end());
std::set<char> set2(s2.begin(), s2.end());
std::vector<char> common;
std::set_intersection(set1.begin(), set1.end(),
set2.begin(), set2.end(),
std::back_inserter(common));
// common = {'l', 'o'}
</char></char></char>
保留重复次数:用 std::unordered_map 统计频次
要得到“两个字符串都出现过的字符,且按最小出现次数重复”,就得统计频次。比如 "aabb" 和 "abbb" 的交集应为 "ab"('a' 各出现 2 次和 1 次 → 取 min=1;'b' 是 min(2,3)=2 → 实际应为 "abb")。
- 先遍历
s1填充std::unordered_map<char int></char> - 再遍历
s2,对每个字符检查是否在 map 中且计数 > 0;若有,加入结果并递减计数 - 注意:顺序取决于
s2的遍历顺序,若需稳定顺序(如按字母序),最后再排序结果
std::string s1 = "aabb", s2 = "abbb";
std::unordered_map<char int> cnt;
for (char c : s1) cnt[c]++;
std::string common;
for (char c : s2) {
if (cnt[c] > 0) {
common += c;
cnt[c]--;
}
}
// common = "abb"
</char>
忽略大小写或只取字母?提前做 std::tolower 或过滤
实际场景中,“相同字符”常隐含规范要求:比如不区分大小写,或只关心 ASCII 字母。这些必须在统计前处理,否则 'A' 和 'a' 被视为不同字符。
- 统一转小写:
std::transform(s.begin(), s.end(), s.begin(), ::tolower) - 只保留字母:
s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return !std::isalpha(c); }), s.end()) - 别在比较时临时转换——那样会破坏原始索引和后续逻辑,尤其用 map 统计时
性能与边界要注意:空字符串、Unicode、宽字符
上述方法默认按 char 处理,适用于 ASCII 场景。遇到中文或 emoji 就失效——因为 UTF-8 下一个汉字占多个 char,而 std::string 的迭代器仍按字节走。
- 纯 ASCII 输入下,
std::unordered_map<char ...></char>安全高效 - 若需支持 Unicode,必须先用 ICU、UTF8-CPP 等库解码为
char32_t序列,再统计;否则所谓“相同字符”只是碰巧字节一致 - 空字符串或一方为空时,所有方法都自然返回空结果,无需额外判空——但如果你用
std::set_intersection且忘了检查输入范围,可能触发未定义行为
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











