字符串匹配

  •     蛮力查找

    通过穷尽遍历的方式查询,效率最低。

int force_search(char * s, int sl, char * p, int pl)
{
    int i(0);
    while ( i + pl <= sl)
    {
        int j(i), k(0);
        while (k < pl)
            if (s[j] == p[k])
                (j ++, k ++);
            else
                break;
        if (k == pl)
            return i;
        ++ i;
    }
    return -1;
}
  •     kmp查找

    kmp算法尽管只有几句代码,但是非常难理解,昨天跟代码走了好几遍,才渐渐晓得主要思想:

    首先分析模式字符串,针对所有的前缀字符串(和全串)获取其所有前缀与后缀字符串的最大公共长度,借助这个长度(即nexts数组)在匹配的时候进行偏移;

void get_nexts(char * p, int pl, int * nexts)
{
    int j(0), k(-1);
    nexts[0] = -1;
    while (j < pl)
        if (p[j] == p[k] || k == -1)
            nexts[++ j] = ++ k;
        else
            k = nexts[k];
}

对nexts数组进行优化,充分利用当前不匹配的字符,尽最大可能右移nexts数组;

void get_nexts2(char * p, int pl, int * nexts)
{
    int j(0), k(-1);
    nexts[0] = -1;
    while (j < pl)
        if (p[j] == p[k] || k == -1)
        {
            (++ j, ++ k);
            nexts[j] = (p[j] != p[k]) ? k : nexts[k];
        }
        else
            k = nexts[k];
}

    然后逐字符比较,遇到不匹配的只是移动模式字符串的指针(或者int型的索引,指示当前待比较的字符),而主串只是一直往后走;

int kmp_search(char * s, int sl, char * p, int pl)
{
    int * nexts = new int[pl + 1];
    get_nexts2(p, pl, nexts);

    int i(0), j(0);
    int indexbegin(0);
    while (j < pl && i < sl)
        if (s[i] == p[j])
            (++ i, ++ j);
        else
        {
            indexbegin = i - nexts[j]; 
            0 == j ? ++ i :j = nexts[j];
        }
    delete[] nexts;
    return j == pl ? indexbegin :  -1;
}
  • 测试
 1     char * mstr = "aaabacaabacaabacabaabb";
 2     char * pstr = "abacab";
 3     
 4 
 5     cout << "========================" << endl;
 6     cout
 7         << force_search(mstr, strlen(mstr), pstr, strlen(pstr))
 8         << endl;
 9     cout
10         << kmp_search(mstr, strlen(mstr), pstr, strlen(pstr))
11         << endl;
12 
13     for (int i = 0; i < 18; ++ i)
14     {
15         pstr = mstr + i;
16         cout << "========================" << endl;
17         cout
18             << force_search(mstr, strlen(mstr), pstr, strlen(pstr))
19             << endl;
20         cout
21             << kmp_search(mstr, strlen(mstr), pstr, strlen(pstr))
22             << endl;
23     }
出自datakv
原文地址:https://www.cnblogs.com/datakv/p/5581488.html