洛谷P1308 [NOIP 2011 普及组] 统计单词数
代码特点通过预处理统一大小写,简化匹配逻辑。精确分割单词并记录位置,符合题目要求。潜在问题标点符号处理:如单词含非字母字符(如"hello!),会被视为合法单词,可能与题目隐含的输入格式假设冲突。位置计算:起始位置从 0 开始,符合题目示例要求。适用场景输入严格符合“单词由空格分隔”的格式时,代码正确性可保证。处理大规模数据时,线性时间复杂度表现良好。
·
原理
问题目标:统计目标单词在文章中出现的次数及首次出现的位置(不区分大小写,要求完全匹配)。
- 输入处理:将目标单词和文章中的每个单词统一转为小写,实现大小写不敏感的匹配。
- 单词分割:将文章按空格分割成独立单词,并记录每个单词的起始位置。
- 精确匹配:仅统计完全相同的单词,排除子串情况。
步骤
- 输入目标单词:转为全小写形式。
- 读取文章:跳过换行符后读取整行。
- 分割单词:
- 跳过连续空格,逐个提取单词并转为小写。
- 记录每个单词的起始位置(在原文章中的索引)。
- 统计匹配:遍历所有分割后的单词,统计与目标单词完全一致的次数,并记录首次位置。
- 输出结果:未找到则输出
-1,否则输出次数和首次位置。
图示法表示步骤(示例:目标单词 "hello",文章 " Hello World HELLO")
- 处理目标单词:转为
"hello"。 - 处理文章:分割为
["hello", "world", "hello"],起始位置为2, 8, 14。 - 统计匹配:找到两次
"hello",首次位置为2。 - 输出:
2 2。
代码关键行注释
for (char &c : target) c = tolower(c);
// 目标单词转为小写,确保大小写不敏感
cin.ignore();
// 清除输入缓冲区残留的换行符,避免影响后续getline
while (pos < article.size() && article[pos] == ' ') pos++;
// 跳过连续空格,定位到单词起始位置
words.emplace_back(word, start);
// 存储小写单词及其在原文章中的起始位置
if (word == target) {
count++;
if (first_pos == -1) first_pos = start;
}
// 完全匹配时更新计数和首次位置
完整代码程序
#include <iostream>
#include <string>
#include <vector>
#include <cctype>
using namespace std;
int main() {
string target;
cin >> target;
// 将目标单词转为小写
for (char &c : target) c = tolower(c);
cin.ignore(); // 清除输入缓冲区的换行符
string article;
getline(cin, article);
vector<pair<string, int>> words; // 存储(小写单词,在原文中的起始位置)
int pos = 0;
while (pos < article.size()) {
// 跳过空格
while (pos < article.size() && article[pos] == ' ') pos++;
if (pos >= article.size()) break;
int start = pos; // 记录单词起始位置
string word;
// 提取并转换单词
while (pos < article.size() && article[pos] != ' ') {
word += tolower(article[pos]);
pos++;
}
words.emplace_back(word, start);
}
int count = 0, first_pos = -1;
for (const auto &[word, start] : words) {
if (word == target) {
count++;
if (first_pos == -1) first_pos = start;
}
}
if (count == 0) cout << -1 << endl;
else cout << count << " " << first_pos << endl;
return 0;
}
时间复杂度
- 时间复杂度:O(N + M),其中 N 是文章长度,M 是分割后的单词数。
- 分割文章需遍历全部字符(O(N))。
- 统计匹配需遍历所有单词(O(M))。
- 空间复杂度:O(N),用于存储分割后的单词和位置。
总结
- 代码特点:
- 通过预处理统一大小写,简化匹配逻辑。
- 精确分割单词并记录位置,符合题目要求。
- 潜在问题:
- 标点符号处理:如单词含非字母字符(如
"hello!"),会被视为合法单词,可能与题目隐含的输入格式假设冲突。 - 位置计算:起始位置从 0 开始,符合题目示例要求。
- 标点符号处理:如单词含非字母字符(如
- 适用场景:
- 输入严格符合“单词由空格分隔”的格式时,代码正确性可保证。
- 处理大规模数据时,线性时间复杂度表现良好。
更多推荐



所有评论(0)