【问题标题】:Return the sub string [duplicate]返回子字符串[重复]
【发布时间】:2019-10-02 09:42:50
【问题描述】:

如何将它用于 x 数量的数字?对于我的方法,它硬编码为 2 个子字符串。还有时间复杂度更低的更好方法吗?这里可能有一个漏洞,需要修正 num im 传递的数量,因为我根本没有使用 um 参数。

【问题讨论】:

  • 你不能编辑和删除问题!!!

标签: c++


【解决方案1】:

您当前的方法存在一些问题,包括硬编码的最大 ngram 数和固定的 ngram 大小。此外,您的短变量名称和缺少 cmets 无助于向正在阅读代码的人解释代码。

更简单的解决方案是使用map 来计算每个ngram 出现的次数,然后找到计数最高的那个。这会给N.logN 时间复杂度。或者unordered_map 会更接近线性时间复杂度。

当然会有一个极端情况,即多个 ngram 出现相同的最高计数。您需要决定应使用多种策略中的哪一种来解决该问题。在我的示例中,我利用 std::map 的内在排序来选择排序顺序最低的 ngram。如果使用unordered_map,您需要一种不同的策略来确定性地解决争用问题。

#include <algorithm>
#include <iostream>
#include <map>
#include <string>

std::string ngram(const std::string &input, int num)
{
    if (num <= 0 || num > input.size()) return "";

    // Count ngrams of size 'num'
    std::map<std::string, int> ngram_count;
    for(size_t i = 0; i <= input.size() - num; i++)
    {
        ++ngram_count[input.substr(i, num)];
    }

    // Select ngram with highest count
    std::map<std::string, int>::iterator highest = std::max_element(
        ngram_count.begin(), ngram_count.end(),
        [](const std::pair<std::string, int>& a, const std::pair<std::string, int>& b)
        {
            return a.second < b.second;
        });

    // Return ngram with highest count, otherwise empty string
    return highest != ngram_count.end() ? highest->first : "";
}

int main()
{
    std::cout << ngram("engineering", 2) << std::endl;
    std::cout << ngram("engineering", 3) << std::endl;
    return 0;
}

【讨论】:

    【解决方案2】:

    我做的和稻谷有点不同,所以我想我会发布它。使用std::set。他解释了这个问题,所以应该得到你的回答。

    struct test {
        test(const std::string& str) :val(str), cnt(0) {}
        test(const test& thet) { *this = thet; }
        std::string val;
        int cnt;
        friend bool operator < (const test& a, const test& b) { return a.val < b.val; }
    };
    using test_set_type = std::set<test>;
    
    const test ngram(std::string A, int num) {
        test_set_type set;
        for (auto it = A.begin(); it < A.end() - num + 1; ++it)
        {
            auto found = set.find(std::string(it, it + num));
            if (found != set.end())
                ++const_cast<test&>(*found).cnt;
            else
                set.insert(std::string(it, it + num));
        }
        int find = -1;
        test_set_type::iterator high = set.begin();
        for (auto it = set.begin(); it != set.end(); ++it)
            if(it->cnt > find)
                ++find, high= it;
        return *high;
    }
    
    
    int main() {
        int num = 2;
        std::string word("engineering");
        std::cout << ngram(word, num).val << std::endl;
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-01
      • 2018-09-27
      • 2014-12-05
      • 1970-01-01
      • 1970-01-01
      • 2020-01-22
      • 1970-01-01
      相关资源
      最近更新 更多