Lx. GreapCity

Description

以字符串形式提供给一段英文文章,编写一个程序。该程序将统计指定字符串中每个单词出现的次数。 我们同时定义单词的长度和出现次数的乘积作为权重,程序最终需要输出权重最高的单词以及其出现的次数。(不限语言,函数自行声明)

Solution

总的时间、空间复杂度为

#include <iostream>
#include <string>
#include <sstream>
#include <cctype>
#include <unordered_map>
#include <algorithm>
#include <vector>
#include <stdexcept>

// 去除标点符号
std::string removePunctuation(const std::string& input) {
    std::string result;
    for (char c : input) {
        if (!std::ispunct(c)) {
            result += c;
        }
    }
    return result;
}

// 找到最大权重的单词
std::pair<int, std::string> findHighestWeightWord(const std::string& input) {
    std::string dePunct = removePunctuation(input);
    std::unordered_map<std::string, int> wordMap;
    std::stringstream ss(dePunct);
    std::string word;

    // 这里我创建了一个std::unordered_map用来统计文章中出现的单词以及其出现的次数
    while (ss >> word) {
        std::transform(word.begin(), word.end(), word.begin(), ::tolower);
        wordMap[word]++;
    }

    // 将std::ordered_map中的元素插入到std::vector的同时计算其权重
    std::vector<std::pair<int, std::string>> priorityWordQ;
    priorityWordQ.reserve(wordMap.size());
    for (auto wordData : wordMap) {
        priorityWordQ.push_back({(wordData.second * wordData.first.size()), wordData.first});
    }

    // 将创建的std::vector变成最大堆
    std::make_heap(priorityWordQ.begin(), priorityWordQ.end());
    // 返回最大堆的第一个元素,即最大权重和单词所组成的std::pair
    return priorityWordQ.front();
}

int main() {
    // Effective Modern C++ Introduction
    std::string input = R"(If you’re an experienced C++ programmer and are anything like me, you initially approached C++11 thinking, “Yes, yes, I get it. It’s C++, only more so.” But as you learned more, you were surprised by the scope of the changes. auto declarations, range-based for loops, lambda expressions, and rvalue references change the face of C++, to say nothing of the new concurrency features. And then there are the idiomatic changes. 0 and typedefs are out, nullptr and alias declarations are in. Enums should now be scoped. Smart pointers are now preferable to built-in ones. Moving objects is normally better than copying them.

There’s a lot to learn about C++11, not to mention C++14.

More importantly, there’s a lot to learn about making effective use of the new capabilities. If you need basic information about “modern” C++ features, resources abound, but if you’re looking for guidance on how to employ the features to create software that’s correct, efficient, maintainable, and portable, the search is more challenging. That’s where this book comes in. It’s devoted not to describing the features of C++11 and C++14, but instead to their effective application.

The information in the book is broken into guidelines called Items. Want to understand the various forms of type deduction? Or know when (and when not) to use auto declarations? Are you interested in why const member functions should be thread safe, how to implement the Pimpl Idiom using std::unique_ptr, why you should avoid default capture modes in lambda expressions, or the differences between std::atomic and volatile? The answers are all here. Furthermore, they’re platform-independent, Standards-conformant answers. This is a book about portable
C++.

The Items in this book are guidelines, not rules, because guidelines have exceptions. The most important part of each Item is not the advice it offers, but the rationale behind the advice. Once you’ve read that, you’ll be in a position to determine whether the circumstances of your project justify a violation of the Item’s guidance. The true goal of this book isn’t to tell you what to do or what to avoid doing, but to convey a deeper understanding of how things work in C++11 and C++14.)";
    auto res = findHighestWeightWord(input);
    std::cout << "Word with highest weight: " << res.second << std::endl;
    std::cout << "Wright: " << res.first << std::endl;
    std::cout << "Frequency: " << res.first/res.second.size() << std::endl;
    return 0;
}