KMP算法

KMP算法

( 一 )Next数组(作用是在模式串中提取加速匹配的信息)

    Next数组储存的是前j-1个字符的匹配 a[0]a[1]a[2]a[3]…a[k-1]和a[j-k]a[j-k+1]…a[j-1] 所能匹配的k的最大值

    Next数组的求解:

    ( 1 )next[0]=-1next[1]=0(j=1,在1j-1的位置上没有字符,属于其他情况)。

   ( 2 )如果next[j]=k,表示有“a[0]a[1]a[2]a[3]…a[k-1]”=a[j-k]a[j-k+1]…a[j-1] 这样的话 则有:

1.a[k]=a[j],即有“a[0]a[1]a[2]a[3]…a[k-1]a[k]”=a[j-k]a[j-k+1]…a[j-1]a[j]” 即有next[j+1]=k+1.

 2.a[k]!=a[j],说明a[j]之前不存在长度为next[j]+1的子串和开头字符起的子串相同此时应该将k回退 寻找有没有长度较短的子串和开头字符起的子串相同。此时的前k个字符已经符合“a[0]a[1]a[2]a[3]…a[k-1]”=a[j-k]a[j-k+1]…a[j-1] ”,故从next[k]进行搜索 直到不存在可以匹配的子串,即此时k=next[k];

    代码实现:

void GetNext()
{
    int j,k;
    j=0;k=-1;
    next[0]=-1;
    while(j<strlen(a))//a为模式串
    {
        if(k==-1||a[j]==a[k])
        {
            j++;k++;
            next[j]=k;
        }
        else k=next[k];
    }
}

( 二 )KMP算法匹配过程

    我们以目标串“aaaaab”和模式串“aaab”为例

    先求出模式串“aaab”的next数组:

    

模式串“aaab”的next数组
j0123
b[j]aaab
next[j]-1012

从开头进行匹配,当j=3时,发现匹配不成功


通过图我们不难得出a[j-1]a[j-2]=b[j-1]b[j-2]


而我们知道next[3]=2;即b[j-2]b[j-1]=b[0]b[1]


因此我们可以不让i动,而j后退,即使a[j-1]a[j-2]与b[0]b[1]对准,此时j=2=next[3]



继续进行如上匹配,可发现j=3时与目标串发生冲突,这时重复上述操作,可使j=2而i不变



最终字符串得以匹配,可以从这一般推到特殊,我在这里就不做过多说明了

模式如下:

i=0;j=0;
while(a和b都没有扫描完)
{
    if(j=-1或者他们所指的字符相同)
        i和j分别增1;
    else
        i不变,j回退到j=next[j];
}
if(j超界) 返回i-b的长度
else 返回-1

对应代码如下:

int KMP()
{
    int i,j;
    while(i<lena&&j<lenb)
    {
        if(j==-1||a[i]==b[j])
        {
            i++;
            j++;
        }
        else
            j=next[j];
    }
    if(j>=lenb)
        return i-lenb;
    else
        return -1;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值