OpenJudge NOI 1.7 25:最长最短单词 | 信息学奥赛字符串处理入门精讲
1. 题目解析与解题思路这道题目要求我们在一段给定的文本中找出最长的单词和最短的单词。看似简单但其中包含了字符串处理的多个核心知识点。我们先来看题目具体要求输入是一个包含多个单词的字符串单词之间用空格或逗号分隔。输出需要给出这段文本中最长的单词和最短的单词每个单词占一行。如果存在多个最长或最短单词输出第一个出现的。在实际解题时我发现有几个关键点需要注意连续的分隔符比如多个空格或逗号连在一起不应该产生空单词最后一个单词后面可能没有分隔符需要准确统计每个单词的长度2. 字符数组解法详解我们先来看使用字符数组的解法这是C语言风格的字符串处理方式也是很多竞赛选手的入门选择。#includebits/stdc.h using namespace std; int main() { char s[205][105]; // 二维数组保存单词 char c; // 当前读取的字符 int w 0, j 0; // w:单词编号 j:字符位置 while((c getchar()) ! \n) { if(c ! c ! ,) { s[w][j] c; // 存储字符到当前单词 } else if(j ! 0) { // 遇到分隔符且当前有单词 s[w][j] \0; // 添加字符串结束符 w; // 准备下一个单词 j 0; } } s[w][j] \0; // 处理最后一个单词 w; int wordNum w; // 单词总数 int maxlen 0, minlen 200; // 初始化长度 int max_i, min_i; // 记录位置 for(int i 0; i wordNum; i) { int len strlen(s[i]); if(len maxlen) { max_i i; maxlen len; } if(len minlen) { min_i i; minlen len; } } puts(s[max_i]); puts(s[min_i]); return 0; }这个解法的核心思路是使用二维字符数组存储分割后的单词逐个字符读取输入遇到分隔符时完成当前单词遍历所有单词比较长度找出最长和最短的我在实际测试时发现几个容易出错的地方忘记处理最后一个单词因为可能没有结尾分隔符没有处理连续分隔符的情况会导致空单词数组大小设置不合理可能导致越界3. string类解法详解对于C选手来说使用string类会让代码更加简洁和安全。下面是用string实现的版本#includebits/stdc.h using namespace std; int main() { string s, word, maxWord, minWord; getline(cin, s); s ; // 统一处理 int wst 0, wlen 0; // 单词起始位置和长度 int minLen 200, maxLen 0; for(int i 0; i s.length(); i) { if(s[i] || s[i] ,) { if(wlen 0) { // 有有效单词 word s.substr(wst, wlen); if(wlen maxLen) { maxWord word; maxLen wlen; } if(wlen minLen) { minWord word; minLen wlen; } } wst i 1; // 下一个单词起始 wlen 0; } else { wlen; // 增加当前单词长度 } } cout maxWord endl; cout minWord endl; return 0; }这个版本有几个优势不需要手动管理内存和数组大小使用substr方法简化了单词提取自动处理字符串长度等操作在实际编码时我建议初学者注意string的substr方法参数是(起始位置, 长度)而不是结束位置统一在字符串末尾添加分隔符可以简化逻辑使用getline读取整行而不是逐个字符4. 常见错误与调试技巧在解决这类字符串处理题目时新手常会遇到以下问题边界条件处理不当字符串开头就是分隔符字符串结尾没有分隔符连续多个分隔符长度统计错误忘记字符串结束符\0不算在长度内中英文混排时字符计数问题数组越界没有预留足够的空间给结束符单词数量超出预设数组大小调试技巧分享使用cout在关键位置输出中间变量值对于边界情况可以手动构造测试用例在OpenJudge上提交前先在本地测试各种情况我常用的测试用例包括空字符串只有一个单词的字符串所有单词长度相同的字符串包含多个连续分隔符的字符串包含标点符号的字符串5. 性能优化与扩展思考虽然这道题的数据规模不大但养成良好的编程习惯很重要。我们可以考虑时间复杂度优化当前解法已经是O(n)最优可以边分割边记录避免二次遍历空间优化不需要存储所有单词只需记录当前最长最短使用滑动窗口思想减少内存使用功能扩展处理更多分隔符如分号、句号输出所有最长/最短单词统计单词长度分布对于想进一步提高的同学可以尝试实现一个通用的字符串分割函数处理Unicode字符和多字节编码用正则表达式实现相同功能6. 竞赛技巧与学习建议在信息学竞赛中字符串处理是基础但重要的技能。我的备赛建议是掌握两种字符串表示方式C风格字符数组更底层需要理解指针和内存C string类更安全易用但要知道内部原理熟练使用关键函数strlen, strcmp, strcpy等C函数string的find, substr, erase等方法多做针对性练习OpenJudge上有大量字符串处理题目从简单题开始逐步提高难度建立自己的代码模板字符串分割模式匹配字符串转换在准备NOI竞赛时我会把这类基础题目反复练习直到能够快速准确地写出无bug的代码。记住竞赛中基础题的稳定发挥是关键。