
1. 从字符数组到string类解题思路的进化第一次接触这道题目时我下意识地选择了字符数组的解法。毕竟对于刚接触编程的同学来说字符数组的操作更直观就像搭积木一样逐个字符处理。但很快我就发现这种看似简单的方法其实暗藏陷阱。字符数组解法最头疼的就是边界条件处理。比如当输入的单词长度小于3时直接访问s[len-3]就会导致数组越界。记得有一次比赛我因为没做长度检查直接丢掉了20分。赛后调试时才发现原来测试用例中有一个单词a——谁能想到这么简单的输入会成为绊脚石呢相比之下string类的解法就显得优雅多了。通过length()方法可以轻松获取字符串长度配合条件判断就能完美规避越界问题。更重要的是string类提供了substr和erase这两个神器让字符串操作变得像切蛋糕一样简单。2. string类成员函数深度解析2.1 substr精准截取的艺术substr函数就像一把精确的手术刀可以让我们轻松获取字符串的任意部分。它的两个参数分别是起始位置和子串长度但很多人容易忽略一个细节起始位置是从0开始计数的。在实际使用中我发现一个实用技巧当只需要获取字符串末尾的几个字符时可以用s.length()减去需要的字符数作为起始位置。比如要获取最后3个字符就是s.substr(s.length()-3, 3)。不过要特别注意当字符串长度不足时这样的操作会抛出异常这就是为什么解法2中要先检查s.length() 3。2.2 erase删除操作的两种姿势erase函数提供了两种删除方式就像瑞士军刀的不同刀片第一种erase(pos, len) 从pos位置开始删除len个字符第二种erase(pos) 从pos位置一直删到字符串末尾在本题中我们用的是第二种方式因为要删除的后缀长度是固定的2个或3个字符。这里有个小技巧删除操作会改变原字符串的长度所以如果连续进行多次删除操作一定要记得每次操作后字符串长度都会变化。3. 实战中的常见陷阱与解决方案3.1 边界条件小细节决定成败在算法竞赛中边界条件往往是失分的重灾区。对于这道题我总结了三个必须检查的边界情况空字符串输入虽然题目可能保证非空但实际比赛中最好处理字符串长度刚好等于要删除的后缀长度如输入er要删除er字符串长度小于要检查的后缀长度如输入a检查ing解法2中的if(s.length() 3)就是针对第三种情况的防御性编程。这种习惯在比赛中能帮你避免很多不必要的失分。3.2 性能考量string操作的效率虽然string类用起来方便但在极端情况下比如超长字符串或高频操作时它的性能可能不如字符数组。不过对于OI比赛来说string类的性能完全够用。我曾经做过测试对长度100万的字符串进行100万次substr操作在现代计算机上也不过几毫秒。4. 代码优化与风格建议4.1 逻辑结构的优化解法2的代码虽然正确但嵌套的if-else结构稍显复杂。我们可以通过提前返回的方式来简化if(s.length() 3 s.substr(s.length()-3) ing) { cout s.erase(s.length()-3); return 0; } if(s.length() 2 (s.substr(s.length()-2) er || s.substr(s.length()-2) ly)) { cout s.erase(s.length()-2); return 0; } cout s;这种写法不仅更清晰而且在比赛中能节省宝贵的编码时间。4.2 变量命名的艺术好的变量名能让代码自文档化。比如解法2中的s1可以改名为suffix这样一眼就能看出它的用途。在紧张的比赛环境中清晰的变量名能大大降低调试难度。5. 从题目到实战string类的更多妙用这道题虽然简单但涉及的技术点可以扩展到很多场景。比如处理文件扩展名.txt - 实现简单的词形还原running - run解析URL路径/article/123 - /article在最近的一次项目中我就用类似的思路处理用户输入的标签自动去除多余的标点符号后缀。这种把竞赛技巧应用到实际开发中的感觉真的很棒。6. 训练建议与资源推荐想要熟练掌握string类的各种操作我建议从以下几个方面入手熟记常用成员函数除了substr和erase还要掌握find、replace、compare等多做字符串处理题目OpenJudge上有大量类似题目比如统计单词数、字符串加密等阅读标准库源码了解string类的底层实现这对理解其性能特征很有帮助对于想深入学习的同学我推荐《C Primer》中关于string类的章节以及cppreference.com上的详细文档。这些资源能帮你全面掌握string类的各种细节。在平时的训练中我习惯把常用的字符串操作封装成工具函数。比如判断后缀的函数就可以这样写bool endsWith(const string s, const string suffix) { return s.size() suffix.size() s.substr(s.size()-suffix.size()) suffix; }这样的小工具积累多了解题时就能事半功倍。