KMP算法

KMP算法

    看了一下网上的KMP算法,发现讲的都不大适合我,个人觉得还是严蔚敏的书上讲的比较简单明了清晰,适合我理解,所以就整理了一下。

    KMP算法之所以叫做KMP算法是因为这个算法是由三个人共同提出来的,就取三个人名字的首字母作为该算法的名字。其实KMP算法与BF算法的区别就在于KMP算法巧妙的消除了指针i的回溯问题,只需确定下次匹配j的位置即可,使得问题的复杂度由O(mn)下降到O(m+n)。

    假设主串为's1s2s3...sn',模式串为'p1p2p3...pm',当主串中第i个字符与模式中第j个字符失配时,主串中第i个字符(i指针不回溯)应与模式中那个字符再比较。

    假设此时应与模式中第k(k<j)个字符继续比较,则模式中前k-1个字符的子串必须满足下列关系式,且不可能存在k'>k满足下列关系式

'p1p2p3...p(k-1)' = 's(i-k+1)s(i-k+2)...s(i-1)'

而已经得到的"部分匹配"的结果是

'p(j-k+1)p(j-k+2)...p(j-1)' = 's(i-k+1)s(i-k+2)...s(i-1)'

由上述两式可得:

'p1p2p3...p(k-1)' ='p(j-k+1)p(j-k+2)...p(j-1)'

令next[j] = k 则

next[j] = 0 当j = 1 时

= Max{k | 1 < k < j 且 'p1...p(k-1)' = 'p(j-k+1)...p(j-1)'}当此集合不为空时

= 1 其他情况

next函数值 j |1 2 3 4 5 6 7 8

    模式串 |a b a a b c a c

  next[j] |0 1 1 2 2 3 1 2

int Index_KMP(SString S, SString T, int pos){
     //利用模式串T的next函数求T在主串S中第pos个字符之后的位置的KMP算法。其中,T非空,1<=pos<=StrLength(s).
    i = pos;  j = 1;
    while(i <= S[0] && j <= T[0]){
        if(j == 0 || S[i] == T[j]){i++;j++}	//继续比较后续字符串
        else j = next[j];		//模式串向右移动
    }
    if(j > T[0]) return i - T[0];	//匹配成功
    else return 0;
}



上面的next尚有缺陷例如

j | 1 2 3 4 5 

模式  | a a a a b

       next[j] | 0 1 2 3 4

  nextval[j] | 0 0 0 0 4

改进的算法为:

void get_nextval(SString T, int next[]){
    //求模式串T的next函数值并存入数组nextval[]
    i = 1; nextval[1] = 0; j = 0;		//i存储的匹配到哪,j为匹配的数值
    while(i < T[0]){
        if(j == 0 || T[i] == T[j]){
            ++i; ++j;
            if(T[i] != T[j]) nextval[i] = j;
            else nextval[i] = nextval[j];
        }else j = nextval[j];
    }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值