KMP算法

KMP算法

KMP算法是一种改的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。

问题:给一个目标串T:ABABCDEFG,模式串P:ABC,找出P在T中完全匹配出现的位置

1.简单的字符串模式匹配
遍历每一个T的位置,从该位置往后挨个元素和P中元素对比是否相同,相同则一起往后遍历,不同则移动T的指针i。复杂度O(mn).

int str_match(string t, string p){
    int i=0,j=0;
    while(i<t.size()&&j<p.size()){
        if(t[i]==p[j]){
            ++i;
            ++j;
        }else{
            i=i-j+1;
            j=0;
        }

    }
    if(j==p.size()-1)
        return i-j;
    else
        return -1;
}

2.KMP
比如T:ABABCBCD、P:ABABD 匹配,当匹配到第5位时候,T为ABABC,P为ABABD出现不同,其实不必移动到T的第二位从头开始比较(移动i指针),也可以移动j指针,因为P中前面也有AB与T的末位相同。
这个东西不看图很难懂的,目前没时间画图改博客,抢先看以下两个链接,两个兄弟讲得很好
http://www.cnblogs.com/tangzhengyue/p/4315393.html
https://www.cnblogs.com/yjiyjige/p/3263858.html

vector<int>get_next_ori(string p){
    vector<int>next(p.size(),0);
    next[0]=-1;
    int k=-1,j=0;
    while(j<p.size()){
        if(k==-1||p[j]==p[k]){ //k在最前或者模式串两个p和j位置相等
            next[++j]=++k;  //j下一个位置不匹配的话就退回到k的下一个位置,因为j之前和k之前的匹配
        }else{
            k=next[k] //如果k不在最前并且模式串不等,k的位置在往前回退到和k匹配的位置next[k]
        }
    }
    return next;
}
/*
上面找next数组方法在T:ABACBC P:ABAB的时候第3位C和B不匹配,会退到next[3]=2,但是T中的AC和P中的前面两个字母AB还是不匹配,因为P:ABAB的p[j]=p[next[j]],
所以回退回去还是一样的字母,肯定还不匹配,这个时候直接在回退到next[k]就可以,如果p[++j]!=p[next[++j]](即p[++j]!=p[++k])的话,可以直接设置next[j]=k
*/
vector<int>get_next(string p){
    vector<int>next(p.size(),0);
    next[0]=-1;
    int k=-1,j=0;
    while(j<p.size()){
        if(k==-1||p[j]==p[k]){
            if(p[++j]==p[++k]){
                next[j]=next[k];
            }else{
                next[j]=k;
            }
        }else{
            k=next[k]
        }
    }
    return next;
}
int KMP(string t, string p){
    int i=0,j=0;
    vector<int>next=get_next(p);
    while(i<t.size()&&j<p.size()){
        if(t[i]==p[j]){
            ++i;
            ++j;
        }else{
            j=next[j];
        }
    }
    if(j==p.size()-1)
        return i-j;
    else
        return -1;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值