KMP算法及其改进算法(随笔)

本文详细介绍了KMP算法的工作原理,包括模式匹配过程、状态推进和next数组的计算。通过分析不匹配时如何避免回溯提高效率,探讨了KMP算法的改进,讲解了nextval数组的推导过程,以提高匹配效率。
摘要由CSDN通过智能技术生成

字符储存在1~length的位置上

简单模式匹配

​ 思路:从主串的第一个位置起和模式串的第一个字符开始比较,如果相等,则继续逐一比较后续字符;否则从主串的第二个字符开始,再重新用上一步的方法与模式串中的字符做比较,以此类推,直到比较完模式串中的所有字符。若匹配成功,则返回模式串在主串中的位置;若匹配不成功,则返回一个可区别于主串所有位置的标记,如“0”。

int index(Str str,Str substr)
{
   
    int i = 1,j = 1,k = 1;//串从数组下标1位置开始存储,初值为1
    while(i <= str.length && j <= substr.length)
    {
   
        if(str.ch[i] == substr[j])
        {
   
            i++;
            j++;
        }
        else
        {
   
            j = 1;
            i = ++k;//匹配失败,i从主串的下一个位置开始匹配,k储存了主串上一次的起始位置
        }
    }
    if(j > substr.length)
        return k;
    else ruturn 0;
}

主串(ABABCABCACBAB)和模式串(ABCAC)匹配过程

KMP算法

​ 设主串为s1s2…sn,模式串为p1p2…pm,在上面的匹配过程中,经常出现一个关键状态(表2),其中i和j分别为主串和模式串中当前参与比较的两个字符的下标。

​ 模式串的前部某子串P1P2…Pj-1与主串中的一个子串Si-j+1Si-j+2…Si-1匹配,而Pj与Si不匹配。每当出现这种状态时,简单模式匹配算法的做法是:一律将i赋值为i-j+2,j赋值为1,重新开始比较。这个过程反映到表2中可以形象地表示为模式串先向后移动一个位置,然后从第一个字符P1开始逐个和当前主串中对应的字符做比较;当再次发现不匹配时,重复上述过程。这样做的目的是试图消除Si处的不匹配,进而开始Si+1及其以后字符的比较,使得整个过程得以推进下去。

​ 如果在模式串后移的过程中又出现了其前部某子串P1P2…与主串中某子串…Si-2Si-1相匹配的状态,则认为这是一个进步的状态。因为通过模式串后移排除了一些不可能匹配的状态,来到了一个新的局部匹配状态,并且此时Si有了和模式串中对应字符匹配的可能性。为了方便表述,记表中描述的状态为Sk,此处的新状态为Sk+1,此时可以将简单模式匹配过程看成一个由Sk向Sk+1推进的过程。当由Sk来到Sk+1时有两种情况可能发生:其一,S处的不匹配被解决,从si+1继续往下比较,若来到新的不匹配字符位置,则模式串后移寻找状态Sk+2;其二,Si处的不匹配仍然存在,则模式串继续后移寻找状态Sk+2如此进行下去,直到得到最终结果。

说明:为了使上边其一与其二的表述看起来清晰工整且抓住重点,此处省略了对匹配成功与失败这两种容易理解的情况的描述。

说明:模式串后移使P1移动到Si+1,即模式串整个移过Si的情况也认为是Si处的不匹配被解决。试想,如果在匹配过程中可以省略掉模式串逐渐后移的过程,而从Sk直接跳到Sk+1,则可以大大提高匹配效率。带着这个想法,我们把Sk+1状态添加到表2中得到表3。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

「已注销」

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值