c ++有效地获取带索引的字符串的子串

时间:2017-03-21 08:40:15

标签: c++ c++11 substr

在我的项目中,我必须从index = 0开始迭代一个大字符串并获取长度为k substring。我已经实现了string :: substr()并想知道是否还有其他有效的方法。

例如:

std::string S ="ABCDEFGHIJKLMN"

我需要从S.的开头开始得到长度= 5的所有子串。就像 "ABCDE""BCDEF""CDEFG"等等。

我的实现如下:

    void geekfunc(std::string &str)
{
    unsigned int index=0;
    for (; index<=(str.size()-K);++index)
    {
        ++myseqmap[str.substr(index,K)];
    }
}

此功能被称为千万次,我欢迎其他方法尝试。

3 个答案:

答案 0 :(得分:5)

如果您使用的是C ++ 17,则可以使用string_view作为参数和映射键类型。这样,每次调用substr时,您都不会复制字符串内容。只需确保传递给函数的字符串在您的地图仍处于使用状态时不会被销毁或修改。

std::map<std::string_view, std::size_t> myseqmap;

void geekfunc(std::string_view str)
{
    unsigned int index=0;
    for (; index<=(str.size()-K);++index)
    {
        ++myseqmap[str.substr(index,K)];
    }
}

答案 1 :(得分:3)

如果您确实需要创建子字符串的副本(string::substr执行),我相信您无法通过对内存管理器的Omega(m)次调用和Omega(m * k)复制步骤来解决此问题总计,m = n - k + 1。这是因为标准要求每个字符串管理自己的内存。不允许共享(例如使用写时复制习语),因此每个子字符串将从原始字符串中复制其内容。

如果不需要副本且您的编译器已提供std::string_view,您可以尝试使用它。与string不同,string_view只保存指向字符和大小的指针(这正是您从无论如何创建子字符串的方式)。可以使用string::data获取所需指针。

但是,当使用string_view时,您必须确保原始字符串保留在范围内,只要容器包含子字符串并且在创建子字符串后它不会被更改,因为这可能会使由string_view持有的指针。可以通过将所有内容包装在一起来解决这些问题:

struct substrings{
    const std::string original;
    container<string_view> substrings;
};

container是您选择的任何容器。

答案 2 :(得分:0)

您正在为任何给定的字符串搜索K-mers

static vector<string> find_kmers(string Text, int k)
{
    vector<string> kmers;
    int n = Text.length();;

    for (int i = 0; i < n-k+1; i++)
       kmers.push_back(Text.substr(i, k));               
    return kmers;
}