KMP新理解


#define MAX_NUM 100

void kmpNext(const char pattern[], int pattern_len, int next[])
{
    int i, j;

    next[0] = -1;

    //超级关键的初始化~
    i = 0;
    j = -1;
    while (i < pattern_len)
    {
        //i是后缀结尾,j是前缀结尾
        //先找匹配项,然后自增,来判断当前项的next
        //以往的思路都是通过前next直接求当前
        //但有一个bug是我们每次都必须找匹配
        //这样子做完全做到了
        //j==-1是个特例,只需判断和字符串首的情况即可
        if (j == -1 || pattern[i] == pattern[j])
        {
            i++;
            j++;

            if (i >= pattern_len)
                break;

            if (pattern[i] == pattern[j])
                next[i] = next[j];
            else
                next[i] = j ;
        }
        else
            j = next[j];
    }
}

int kmp(const char str[], int str_len, const char pattern[], int pattern_len)
{
    int i, j;

    int next[MAX_NUM];
    kmpNext(pattern, pattern_len, next);

    i = j = 0;
    while (i < str_len - pattern_len && j < pattern_len)
    {
        if (str[i] == pattern[j])
        {
            i++;
            j++;
        }
        else
        {
            if (next[j] == -1)
            {
                j = 0;
                i++;
            }
            else
                j = next[j];
        }
    }

    if (j < pattern_len)
        return -1;
    else
        return i - pattern_len + 1;
}

这次的思路是正确的..


next[i]表示i之前的字符串满足前缀/后缀组合的最大长度,也就是我们下次进行比对匹配的位置(因为前缀从0开始,所以长度即为下标)


而在next的循环中,不变式为"以j-1为结尾的前缀同以i-1结尾的后缀是匹配的(j=-1时为特例,表示开始)",所以当j/i匹配时,我们就可以直接计算i+1对对应的next值了.


这个和以前的思路不同..以前是试图通过i-1来计算i,而现在是得到i,然后求i+1..这个思路明显很高明




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值