acm从入门到放弃——day11

1.KMP算法 是用来处理一对一的匹配的。
朴素的匹配算法,或者说暴力匹配法,就是将两个字符串从头比到尾,若是有一个不同,那么从下一位再开始比。这样太慢了。所以KMP算法的思想是,对匹配串本身先做一个处理,得到一个next数组。这个数组是做什么用的呢?next [j] = k,代表j之前的字符串中有最大长度为k 的相同前缀后缀。记录这个有什么用呢?对于ABCDABC这个串,如果我们匹配ABCDABTBCDABC这个长串,当匹配到第7个字符T的时候就不匹配了,我们就不用直接移到B开始再比一次,而是直接移到第5位来比较,岂不美哉?所以求出了next数组,KMP就完成了一大半。next数组也可以说是开始比较的位数。

计算next数组的方法是对于长度为n的匹配串

如何去求next数组呢?k是匹配下标。这里没有从最后一位开始和第一位开始分别比较前缀后缀,而是利用了next[i-1]的结果。而且我觉得这样理解起来会好一点。求出next就完成了一半了。

void getnext()//获取next数组
{
    int i,n,k;
    n=strlen(ptr);
    memset(next,0,sizeof(next));
    k=0;
    for(i=1;i<n;i++)
    {
        while(k>0 && ptr[k]!=ptr[i])//在无子串的时候不会到这里
            k=next[k];//如果不匹配就回溯到next[k]
        if(ptr[k]==ptr[i]) k++;//匹配到之后就k++
        next[i+1]=k;//将匹配到的字符个数存入
	//next表示的是匹配长度
    }
}

算法导论算法循环是从1到n而不是从0到n-1,所以在下面匹配的时候需要j=next[j+1]。

int kmp(char *a,char *b)//匹配ab两串,a为父串
{
    int i=0,j=0;
    int len1=strlen(a);
    int len2=strlen(b);
    getnext();
    while(i<len1&&j<len2)
    {
        if(j==0||a[i]==b[j])
        {   i++;j++;       }
        else j=next[j+1];//到前一个匹配点
    }
    if(j>=len2)
        return i-j;
    else return -1;
}

这里next数组的作用就显现出来了。最后返回的是i-j,也就是说,是从i位置前面的第j位开始的,也就是上面说的,next数组也可以说是开始比较的位数。也就是说,在父串的i位比的时候已经是在比子串
的第j位了

看一送二的字符串匹配算法(手动滑稽)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值