KMP算法详解

时间复杂度:o(m+n)

空间复杂度:o(n)

m:主串

n:子串

作用:

在一个已知的字符串中查找子串的位置。

思路:

假设有主串z和模板串(子串)m

主串:A  B  B  A  B   B   A   A  B  A   A

子串:A  B  B  A  B   A    A

下标:1  2   3  4  5   6    7

由上图可知,主串与子串在下标为6的位置不匹配,我们此时需要做的是找出子串与主串的最长相等的前缀与后缀。如:

主串:A  B  B  A  B   B   A    A  B   A  A

子串:A  B  B  A  B   A    A

下标:1  2   3  4  5   6    7

子串中的下标为6的字符A,此时开一个next数组存储当前A的下标,为next[6],在A字符前面找最大的前缀与后缀(注意:此时不能找子串本身作为最长前缀,这没有意义)。

如上图,

主串:A  B  B  A  B    A   A   B    A   A

子串:A  B   A  B   A    A    (AB称为子串的公共前后缀)

下标:1  2   3  4  5   6    7

A的最大前(后)缀为AB,如图

 

ABBABA

此时移动子串使得下标为 3的子串前缀与主串后缀对齐:

主串:A  B  B  A  B     A     B   A     A

子串                 A  B      A    B   A    A    (AB称为子串的公共前后缀)//此时是将子串的前缀                                      ^                                                                        // 移动到后缀的位置

下标:             1  2   3  4  5   6    7

依次类推,直到子串与主串匹配成功时,匹配结束。

核心代码:

// s[]是主串,p[]是子串,n是s的长度,m是p的长度
//求子串的Next数组:
for (int i = 2, j = 0; i <= m; i ++ )
{
    while (j && p[i] != p[j + 1])//不匹配
       j = ne[j];
    if (p[i] == p[j + 1])//匹配
       j ++ ;//继续向后遍历
    ne[i] = j;
}

// 匹配过程
for (int i = 1, j = 0; i <= n; i ++ )
{
    while (j && s[i] != p[j + 1]) 
        j = ne[j];
    if (s[i] == p[j + 1]) 
        j ++ ;
    if (j == m)
    {
        j = ne[j];
        // 匹配成功后的逻辑
    }
}

最后要说的就是一定要理解过程,不要死记代码模板。 

觉得好的点个小赞,有错误请指出,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值