第七周 字符串匹配

BF算法,kmp算法

 

BF:时间复杂度为 O(m*n)

 

 

 

 

int Index_BF(SString S, SString T, int pos)
{
    int i = pos, j = 1;
    while (i <= S.length &&j <= T.length)
    {
        if (S.ch[i] == T.ch[j])
        {
            ++i;
            ++j;
        }
        else {
            i = i - j + 2;
            j = 1;
        }
    }
        if (j > T.length)
            return i - T.length;
        else
            return 0;
}

模式串和主串均是存放于字符数组中。(这里是从下标为1开始存储,以便后面操作)

BF比较简单,直接暴力匹配。每次匹配失败,i 回溯到本轮起始位置的下一位。(效率较低)

测试:

结果:

 

————————————————————————————————————————————————————————————————————

————————————————————————————————————————————————————————————————————

——————————————————————————————————————————————————————————————————-——

KMP:时间复杂度为O(m+n)

因为kmp的思想要写的过程太多(我懒得打字),还有结合字符串图更清晰

所以借鉴:https://www.cnblogs.com/yjiyjige/p/3263858.html

 感觉kmp还是很好理解,老师让我讲一遍却又表达不清楚(自己能懂就是不知道怎么把它完整表达出来)

 主要就是 i不用回溯,设立了next[ ]值,即k值,模式串中失配位对应的k值即为下一轮 j重新开始匹配的位置

至于k值得来历,简单点讲 就是为了模式串与主串匹配时减少BF无意义的比较情况,需要在部分匹配成功的

情况下 一次移动k-1 位来提高效率。假设在S主串中的第i位,T模式串的第j为失配,那么i不动,下一次匹配就从第j位

对应的k值开始(j=k=next [ j ]),即下一次从模式串的第k位开始匹配。

计算k值:从kmp算法中,失配后比较的是S的第 i 位与T的第 k 位,那么T中 k 前面的串(k-1)个字符肯定是和S中

i 的前面(k-1)个字符是匹配的。由匹配成功的部分可以得知:S中的i 前面(k-1)个字符又与T中j 前面的(k-1)个字符

是已经匹配成功的,所以前面两句话就等于:

                 T[1...k-1] = T[ j-(k-1)...j-1]

从上面的式子可以看出模式串与主串的比较 变成了模式串自己前缀和后缀的比较,这样找到模式串前缀与后缀所能匹配的最大

长度就等于我们的k-1,也就找出了k;

 

int Index_KMP(SString S, SString T, int pos, int next[])
{
    int i = pos, j = 1;
    while (i <= S.length&&j <= T.length)
    {
        if (j == 0 || S.ch[i] == T.ch[j])
        {
            ++i;
            ++j;
        }
        else
            j = next[j];
    }
    if (j > T.length)
        return i - T.length;
    else
        return 0;
}

 

下面是next[ ]值计算

例子:

 

 

算法:

 

 上面的next值在某些情况下仍有点缺陷,所以有了一个修正next算法

 

修正next算法:

 

结果:

  

 

 

 

 kmp算法还是挺重要的,理解清楚了还应该记住模板,说不定日后或者OJ用得着呢。