c++oding="utf-8" ?>
“字符串减法”指递归擦除成对括号及其内容,非标准运算符重载;需用栈匹配括号、标记待删区间并倒序删除,以支持嵌套、避免索引偏移,时间复杂度o(n)。

什么是“字符串减法”:实际是括号内容的递归擦除
这不是标准库里的 std::string 运算符重载,而是常见业务需求——比如清理日志、预处理模板、剥离注释式括号内容(如 (临时说明) 或 {调试信息})。关键在于:括号必须成对、嵌套需递归处理,不能简单用 find + erase 扫一遍就完事。
用 stack 模拟括号匹配,一次遍历完成擦除
手动维护一个栈记录左括号位置,遇到右括号就弹出并标记待删区间。这样避免反复调用 erase 导致多次内存搬移,时间复杂度稳定在 O(n)。
实操建议:
- 遍历字符串时,遇到左括号(如
'('、'['、'{')就把当前索引压栈 - 遇到对应右括号时,从栈顶取出左括号位置,把该区间(含括号)加入待删集合
- 用
std::set<:pair int>></:pair>存区间,最后倒序删除(避免索引偏移) - 如果只要支持一种括号对(如仅小括号),可省略栈,改用计数器;但多类型或需验证合法性时,栈更稳妥
示例片段(仅处理小括号):
std::string removeParentheses(const std::string& s) {
std::string res;
std::stack<int> stk;
std::vector<bool> skip(s.size(), false);
for (int i = 0; i
<h3>regex_replace 为什么容易出错:贪婪匹配与嵌套失效</h3>
<p>有人试过 <code>std::regex_replace(s, std::regex(R"(\(.*?\))"), "")</code>,但这是错的——它只删最内层或单层,无法处理 <code>"a(b(c)d)e"</code> → 应得 <code>"ae"</code>,而正则默认非递归,结果可能是 <code>"a(c)e"</code> 或根本删不干净。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill4025" title="C++ 算法竞赛自动化测试数据生成与校验框架"><img
src="https://img.php.cn/upload/skill/000/000/081/178988956499722.jpg" alt="C++ 算法竞赛自动化测试数据生成与校验框架" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill4025" title="C++ 算法竞赛自动化测试数据生成与校验框架" class="overflowclass">C++ 算法竞赛自动化测试数据生成与校验框架</a>
<p class="overflowclass">根据原题生成新题面、验证器及完整测试数据,自动套用 testlib 模板,用于用户要求生成测试数据时。</p>
</div>
<a rel="nofollow" href="/xiazai/skill4025" title="C++ 算法竞赛自动化测试数据生成与校验框架" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<p>常见错误现象:</p>
<ul>
<li>
<code>std::regex</code> 在 GCC libstdc++ 中对深度嵌套支持弱,甚至触发 <code>std::regex_error</code>
</li>
<li>点号 <code>.</code> 默认不匹配换行,若括号跨行就漏删</li>
<li>未转义括号字符(如写成 <code>"(.*)"</code> 而不是 <code>R"(\(.*?\))"</code>)导致编译失败或误匹配</li>
</ul>
<h3>要不要考虑 Unicode 和宽字符?</h3>
<p>如果输入含中文括号(如 <code>(中文括号)</code>)、emoji 或 UTF-8 多字节字符,直接按 <code>char</code> 索引操作会切裂字符,导致乱码或越界。</p>
<p>此时必须先做 UTF-8 解码,用 <code>std::u8string</code>(C++20)或第三方库(如 ICU、utf8cpp)迭代 Unicode 码点。否则哪怕逻辑正确,输出也是损坏的。</p>
<p>简单判断方式:检查字符串中是否存在字节值 > 127 的 <code>char</code>,且你不确定来源编码——那就别碰裸 <code>std::string</code> 下标擦除。</p>
<p>嵌套括号的边界判定、多字节字符的索引对齐、空括号 <code>"()"</code> 是否保留——这些细节不显眼,但线上出问题时最难定位。</p></bool></int>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










