Codeforces 71A:Way Too Long Words 错误复盘

cancel
这次提交的核心问题

题目并不难,错误主要集中在输入协议和输出边界:漏读第一行的 n、把一个单词放进多余的长度循环、把 > 10 写成了错误的边界判断,以及没有为每个单词输出换行。

题目要求

第一行输入一个整数 n,表示后面有多少个单词;接下来输入 n 个单词。

  • 单词长度 大于 10 时,缩写为:首字符 + 中间字符数量 + 尾字符。
  • 单词长度 小于等于 10 时,原样输出。
  • 每个单词占一行。

例如:

localization

长度为 12,缩写为:

l10n

10 是中间字符的数量,不是单词总长度减去首尾字符后的文字内容。

四个错误及修正

1. 漏读第一行的 n

题目第一行先给出单词总数。如果不读取 n,程序就无法准确知道什么时候停止,也容易把测试数据或下一组输入误当成单词。

正确的输入骨架是:

int n;
cin >> n;

while (n--)
{
    string word;
    cin >> word;
    // 处理一个单词
}

这里的循环次数由题目输入决定,而不是由某个单词的长度决定。

2. 多余的长度循环导致重复输出

错误思路类似:

for (int i = 0; i < count; i++)
{
    cout << word;
}

如果 count 是单词长度,那么一个 4 位单词会被输出 4 次。题目要求的是“每个单词处理一次”,因此外层只需要遍历 n 个单词,单词内部不需要再按长度重复输出。

正确的结构是:

读取一个单词
    ↓
判断长度
    ↓
输出一次结果
    ↓
换行

3. 边界必须是严格大于 10

题目要求:只有长度 > 10 的单词才缩写。

if (word.size() > 10)
{
    // 缩写
}
else
{
    // 原样输出
}

长度为 10 的单词必须原样输出,因此不能写成 >= 10。这类边界条件要特别用长度为 10 和长度为 11 的样例检查。

4. 每个单词后都要换行

输出完一个单词后立即写入换行:

cout << result << '\n';

也可以使用 endl,但竞赛代码中通常使用 \n,避免不必要的刷新:

cout << result << endl;

如果忘记换行,多个答案会连在同一行,即使缩写逻辑正确,也会被判错。

正确的 C++ 实现

#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;

    while (n--)
    {
        string word;
        cin >> word;

        if (word.size() > 10)
        {
            cout << word.front() << word.size() - 2 << word.back();
        }
        else
        {
            cout << word;
        }

        cout << '\n';
    }

    return 0;
}

为什么 word.size() - 2 是安全的?

它只在 word.size() > 10 的分支中执行,所以单词长度至少为 11,不会发生无符号整数下溢。首字符和尾字符分别用 front() 与 back() 取得,中间字符数量就是总长度减去 2。

最小测试集

输入:
4
word
localization
internationalization
abcdefghij

输出:
word
l10n
i18n
abcdefghij

重点检查:

测试 预期行为
长度小于 10 原样输出
长度等于 10 原样输出,验证不能写成 >= 10
长度大于 10 输出首字符、长度 - 2、尾字符
多个单词 每个单词只输出一次,并且各占一行

提交前检查清单

  1. 是否读取了第一行的 n?
  2. 是否恰好循环 n 次?
  3. 是否只对每个单词处理一次?
  4. 判断条件是否为 word.size() > 10?
  5. 是否输出了 word.front()、word.size() - 2 和 word.back()?
  6. 每个单词后是否都有 \n?
  7. 是否用长度 10、长度 11 和多个单词进行过测试?

这道题留下的经验

这次错误不是算法复杂度问题,而是“输入数量、循环对象、边界条件、输出格式”没有逐项对齐题面。以后遇到简单题,也应先把题目拆成四个问题:

输入有几组?
每组数据处理几次?
边界条件是什么?
输出格式是否逐项匹配?

把这四项确认完,再写核心判断,通常比直接套循环更不容易出错。