如何在字符串中找到子字符串的所有位置?

Her*_*har 12 c++ string find

我将如何解决这个问题?我想在字符串的所有位置搜索一个大字符串.

Mih*_*yan 14

另外两个答案是正确的,但它们非常慢并且具有O(N ^ 2)复杂度.但是有Knuth-Morris-Pratt算法可以找到O(N)复杂度的所有子串.

编辑:

还有另一个算法,所谓的"Z函数"具有O(N)复杂性,但我找不到这个算法的英文源(也许是因为还有另一个更有名的东西同名--Riman的Z函数),所以将其代码放在这里并解释它的作用.

void calc_z (string &s, vector<int> & z)
{
    int len = s.size();
    z.resize (len);

    int l = 0, r = 0;
    for (int i=1; i<len; ++i)
        if (z[i-l]+i <= r)
            z[i] = z[i-l];
        else
        {
            l = i;
            if (i > r) r = i;
            for (z[i] = r-i; r<len; ++r, ++z[i])
                if (s[r] != s[z[i]])
                    break;
            --r;
        }
}

int main()
{
    string main_string = "some string where we want to find substring or sub of string or just sub";
    string substring = "sub";
    string working_string = substring + main_string;
    vector<int> z;
    calc_z(working_string, z);

    //after this z[i] is maximal length of prefix of working_string
    //which is equal to string which starting from i-th position of
    //working_string. So the positions where z[i] >= substring.size()
    //are positions of substrings.

    for(int i = substring.size(); i < working_string.size(); ++i)
        if(z[i] >=substring.size())
            cout << i - substring.size() << endl; //to get position in main_string
}
Run Code Online (Sandbox Code Playgroud)

  • 你可以测试自己.让我们考虑main_string ="a"(1000000次)+"b"+"a"(1000000次).和substring ="a"(999999次).使用std :: string :: find和@Kiril Kirov的代码你的程序将工作2-3天,但我的一个将立即返回. (4认同)
  • 当确实存在两个确定运行时的参数N_haystack和N_needle时,将字符串查找算法描述为O(N)或O(N*N)有点荒谬.当N_needle = 1时,几乎任何算法都是O(N_haystack).大多数是O(N_haystack*N_needle)或更好,你可以假设N_needle <= C. (4认同)

Kir*_*rov 13

std::string::find.你可以这样做:

std::string::size_type start_pos = 0;
while( std::string::npos != 
          ( start_pos = mystring.find( my_sub_string, start_pos ) ) )
{
    // do something with start_pos or store it in a container
    ++start_pos;
}
Run Code Online (Sandbox Code Playgroud)

编辑:Doh!谢谢你的评论,Nawaz!更好?