原理

问题目标:统计目标单词在文章中出现的次数及首次出现的位置(不区分大小写,要求完全匹配)。

  • 输入处理:将目标单词和文章中的每个单词统一转为小写,实现大小写不敏感的匹配。
  • 单词分割:将文章按空格分割成独立单词,并记录每个单词的起始位置。
  • 精确匹配:仅统计完全相同的单词,排除子串情况。

步骤

  1. 输入目标单词:转为全小写形式。
  2. 读取文章:跳过换行符后读取整行。
  3. 分割单词
    • 跳过连续空格,逐个提取单词并转为小写。
    • 记录每个单词的起始位置(在原文章中的索引)。
  4. 统计匹配:遍历所有分割后的单词,统计与目标单词完全一致的次数,并记录首次位置。
  5. 输出结果:未找到则输出 -1,否则输出次数和首次位置。

图示法表示步骤(示例:目标单词 "hello",文章 " Hello World HELLO"

  1. 处理目标单词:转为 "hello"
  2. 处理文章:分割为 ["hello", "world", "hello"],起始位置为 2, 8, 14
  3. 统计匹配:找到两次 "hello",首次位置为 2
  4. 输出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),用于存储分割后的单词和位置。

总结

  1. 代码特点
    • 通过预处理统一大小写,简化匹配逻辑。
    • 精确分割单词并记录位置,符合题目要求。
  2. 潜在问题
    • 标点符号处理:如单词含非字母字符(如 "hello!"),会被视为合法单词,可能与题目隐含的输入格式假设冲突。
    • 位置计算:起始位置从 0 开始,符合题目示例要求。
  3. 适用场景
    • 输入严格符合“单词由空格分隔”的格式时,代码正确性可保证。
    • 处理大规模数据时,线性时间复杂度表现良好。
Logo

集算法之大成!助力oier实现梦想!

更多推荐