字符串差集非标准概念,分按频次删除(保留顺序,减去B中各字符出现次数)和按集合删除(仅去重,保留A中不在B出现的字符)两种语义,需手动实现。

什么是字符串差集,C++里没有现成函数
字符串差集不是标准库定义的概念,它通常指从字符串 A 中移除所有在字符串 B 中出现过的字符(按出现次数还是仅去重?需先明确)。C++ 的 std::string 没有 difference、set_difference 这类直接作用于字符序列的“差集”接口——std::set_difference 要求输入已排序且是迭代器范围,不能直接喂两个 std::string 就完事。
所以得自己组合:要么用容器辅助统计(如 std::unordered_map),要么借助 <algorithm></algorithm> 配合谓词,或者转成集合再处理。选哪种,取决于你想要“字符级去重差集”还是“保留顺序+按频次删减”的语义。
按字符频次做差:A 减去 B 中每个字符的出现次数
这是最贴近“多集合差集”(multiset difference)的理解:若 B 中某字符出现 3 次,A 中该字符最多被删掉 3 次(哪怕 A 里有 5 次),剩余字符保持原顺序。
- 用
std::unordered_map<char int></char>统计 B 中各字符频次 - 遍历 A,对每个字符 c:若 map[c] > 0,则 map[c]-- 并跳过;否则保留 c
- 注意:char 是 signed 还是 unsigned 取决于平台,但 ASCII 字符(0–127)安全;若涉及扩展字符,建议用
unsigned char转换后作 key
std::string string_difference_by_count(const std::string& a, const std::string& b) {
std::unordered_map<char, int> cnt;
for (char c : b) cnt[c]++;
std::string res;
for (char c : a) {
if (cnt[c] > 0) cnt[c]--;
else res += c;
}
return res;
}按字符集合做差(去重版):A 中不在 B 中出现的字符
这等价于 “A ∩ ¬B”,即只关心“是否出现”,不关心次数。适合快速过滤非法字符或白名单校验场景。
立即学习“C++免费学习笔记(深入)”;
- 把 B 转成
std::unordered_set<char></char>,查询复杂度 O(1) - 直接遍历 A,用
set.find(c) == set.end()判断是否保留 - 比用
std::string::find每次 O(n) 扫描 B 快得多,尤其 B 较长时 - 注意:大小写敏感,如需忽略,统一转小写再进 set
std::string string_difference_by_set(const std::string& a, const std::string& b) {
std::unordered_set<char> forbid(b.begin(), b.end());
std::string res;
for (char c : a) {
if (forbid.find(c) == forbid.end()) res += c;
}
return res;
}用 std::set_difference 前必须排序,且会丢失原始顺序
如果你硬要套用 std::set_difference,它要求两段输入都升序排列,输出也是升序,且自动去重——这意味着你既丢掉了 A 的字符顺序,也丢掉了重复字符。它算的是“字符集合的差”,不是“字符串的差”。
- 必须先对 A 和 B 分别调用
std::sort,再用std::unique去重(否则set_difference行为未定义) - 结果存入 vector 或 string,但顺序是字典序,和原 A 完全无关
- 时间复杂度 O(n log n),比哈希方案慢,还更啰嗦,一般没必要走这条路
真要用,代码类似:std::string a_sorted = a; std::sort(a_sorted.begin(), a_sorted.end()); auto last = std::unique(a_sorted.begin(), a_sorted.end()); a_sorted.erase(last, a_sorted.end()); —— 然后再对 B 做同样操作,最后调用 std::set_difference。
字符频次差和集合差的语义差异,是实际写错最多的地方;传参时搞反 A 和 B 顺序也会导致结果完全颠倒,调试时建议加一两个 assert 校验典型 case。


















