应使用 while 循环配合 s.compare(0, prefix.size(), prefix) == 0 判断并 eraser(0, prefix.size()) 删除所有左端重复前缀,需先检查长度避免越界,c++20 可用 string_view::starts_with 简化。

用 std::string::find 和 std::string::erase 循环删除最左匹配前缀
直接删“所有重复前缀”不是字符串替换,而是反复检查开头是否为指定前缀,是就削掉——比如 "abcabcabcHello" 删掉所有 "abc" 前缀,结果应为 "Hello",而不是把中间的 "abc" 也干掉。
关键点在于必须循环判断 substr(0, prefix.length()) == prefix,不能只删一次。常见错误是写成单次 erase 或误用 replace。
- 用
while循环,条件是s.substr(0, prefix.size()) == prefix(注意先检查长度,避免越界) - 每次匹配成功后调用
s.erase(0, prefix.size()) - 不要用
find(0)查找再删——find返回的是首次出现位置,不是“是否在开头”,容易误删中间内容
安全写法:先校验长度再比较,避免 substr 抛 std::out_of_range
substr(0, n) 在 n > s.length() 时会抛异常,而前缀比原串还长是常见边界情况(比如空串、前缀为 "xyz" 但字符串是 "ab")。必须前置长度检查。
正确顺序是:if (s.length() >= prefix.length() && s.substr(0, prefix.length()) == prefix)。更高效一点可改用 s.compare(0, prefix.length(), prefix) == 0,它内部自带长度保护,且不构造临时子串。
- 推荐用
s.compare(0, prefix.size(), prefix) == 0替代substr+== - 如果
prefix为空,compare仍安全,但逻辑上应拒绝空前缀(否则无限循环) - 对 const 字符串或频繁调用场景,把
prefix.size()提到循环外存为局部const size_t len = prefix.size();
用 std::string_view 避免拷贝(C++17+)
如果只是做前缀判断,不需要修改原始字符串,std::string_view 能跳过构造 substr 的开销。但本题目标是“删除”,所以最终还是要操作原串;不过判断阶段可用 string_view 加速。
例如:将原字符串视作 std::string_view sv = s;,然后循环用 sv.starts_with(prefix)(C++20)或手写比较。但注意:C++17 没有 starts_with,得自己比;C++20 可直接用,简洁且安全。
- C++20 环境下,
while (std::string_view(s).starts_with(prefix)) { s.erase(0, prefix.size()); }是最简写法 - C++17 及以下,坚持用
compare更稳,string_view仅当确定生命周期可控时才用于判断 - 别为了用
string_view而把s强转成string_view后又去erase——string_view不拥有数据,不能修改
为什么不用 std::regex_replace?
有人想到用正则匹配行首重复前缀,比如 ^abc,但 regex_replace 默认不支持“贪婪地从左反复剥离”,它是一次性扫描。即使写成 ^(abc)+,也只能匹配连续前缀一次(如 "abcabcabc" 整体),无法做到“删完一个再看剩下开头是不是还匹配”。而且正则启动开销大,短字符串得不偿失。
-
regex_replace(s, std::regex("^" + std::regex_replace(prefix, std::regex(R"(\|.|^|$|?|*|+|(|)|[|]|{|})"), R"(\$&)")), "")—— 这种写法既难读又易错,还要转义前缀里的正则元字符 - 性能上,循环
compare是 O(k·m),k 是重复次数,m 是前缀长度;正则是 O(n),但常数极大,且初始化 regex 对象代价高 - 除非前缀本身含通配逻辑(比如“以 a 或 b 开头的任意三字符”),否则纯前缀剥离没必要上正则
真正容易被忽略的是:前缀可能包含 null 字符(' '),这时 std::string 仍能正常存取和比较,但若误用 C 风格函数(如 strncmp)或传给 C 接口,就会提前截断。只要全程用 std::string::compare 或 string_view,就不存在这个问题。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











