KMP算法

匹配字符串,大多数人都会想到一种方法,那就是一个一个比如果相同,就比下一个,不同,就把模式串的索引变为0,把主串的索引加一,重新开始比较,但是这样的话,在极端情况下(如匹配aaaaaaaaaaab,aaaaaaab),要比较m*n次才能得到正确结果,那么接下来,就给大家介绍一种新的匹配方法,KMP算法,他能够大大的降低比较次数
A:ababababacd
B:ababac
假设匹配这两个字符串,在b串下标为5(c)时发现不匹配,这时,一般的想法是,把A串的初始下标移到1,从头开始与B串比较。B串下标为5之前的3个字母,与从0起的3个字母是一样的(aba),而我们前面已经得到了c之前的所有字符串都与A串相应位置字母匹配。那么A串的最后一个不匹配的前面3个字母也是aba,那么为什么不把B串下标移动到aba的下一个字母(也就是3),再与A串比较呢,也许有人会想,如果A的下标不变的话,万一前面还有更长的字符串可以匹配呢?但是那是不可能的,假设前面有一个更长的字串能够被匹配,因为前面匹配的长度是比B串要短的,所以上面的字符串势必会匹配到当前位置,也就是说,B串最前面的4位要等于c(未匹配字符)之前4位,但我们已经知道,最长是只有3位
a(baba)babacd i
(abab)ac j
也就是说,我们只要知道,每个字符之前的字串,最长的前缀与后缀相等的长度就可以不用移动i而只需移动j就行了,只要求出一个关于B串的最长公共前后缀的长度就行了。
那么我们就可以采用上面的方法,但是主串和模式串都变成B来求最长公共前后缀
因为我们是算这个数之前的最长公共前后缀,所以第一个数赋值为0,但是为了区分第一个数我们把它赋值为-1(最长公共前后缀长度)
ababac
ababac 不同为0
ababac
ababac 相同为1
ababac
ababac 继续下一个相同为2
ababac
ababac 继续下一个相同为3
ababac
ababac 继续下一个不同
跳到下一个位置,也就是我们刚刚求的b之前最长公共前后缀为1
跳到1继续比,不同,1之前的最长公共前后缀为为0(不算自身)所以跳到0继续比不同变为-1赋值为0,开始算下一个

int* getNext(char* T,int len)
{   //建立Next数组
    int* Next=(int*)malloc(sizeof(int)*len);
    //创建需要的变量(i为上面指针,j为下面指针)并给数组第一个元素赋值
    int i=-1,k=0;
    Next[0]=-1;
    while(k<len-1)
    {
    if(i==-1||T[k]==T[i])
    {
        Next[++k]=++i;
    }else
        i=Next[i];
    }
    return Next;
}
int KMP(char* S,int len1,char* T,int len2){
    int* Next=getNext(T,len2);
    int i=0,j=0;
    while(i<len1&&j<len2){
        if(S[i]==T[j]){
            ++i;
            ++j;
            }
        else if(Next[j]!=-1){
            j=Next[j];
            }
        else{
            ++i;
            j=0;
        }
    }
    if(j==len2)
        return i-j;
    return -1;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值