10月14日总结+kmp入门

本文深入解析KMP算法在字符串匹配问题中的优化原理及其实现步骤,通过对比暴力解法,阐述KMP算法如何避免无意义的重复比较,提高匹配效率。并提供next数组与KMP匹配过程的代码实现,探讨KMP算法在模板题及变式问题如求最长公共子序列的应用。

昨天又看了一天的kmp的博客,结果是一直在套着模板做题,完全没理解,简单的模板题很容易A,但稍微考察思想的题就看不懂了,到了晚上偶然翻了翻蓝书,感觉弄懂了点。

下面是分析过程:思路还是有点乱,也只能是自己看,,,再沉淀一下应该会理解的更好。

KMP:

解决的问题:字符串的匹配问题;

分析:

假设现在有两个字符串:母串ababbbabac,模板串abac;问题时查找模板串在母串中出现的位置;

暴力解法:

1、将母串以及模板串的首端对齐;

2、模板串长度范围内逐个对比母串与模板串的元素;

3、若完全一样,匹配成功;否则,匹配失败;

4、将模板串首端与母串第二位对齐,重复过程2、3,直至模板串首位与母串最后一个元素对齐;

优化:

例如上例,当母串的abab与模板串的abac匹配时,我们发现最后一个元素不一致,所以此时按照暴力解法,我们应该将模板串的首位与母串的第二位对齐,再重复搜索(暴力),但根据实际情况,我们知道上述移位操作是毫无意义的,有意义且正常的操作是将模板串的首位与母串的第三位对齐,再继续遍历,同理,下次应当将模板串首位与母串倒数第四为对齐;所以,我们要找一种方法,得到 正常思考 中模板串首位应当移动的位置。

容易发现,这种正常思考中的移动,其实就是去寻找模板串与母串已经匹配的部分(模板串的前多少位)的模板串的前缀(这里不含最后一位)与母串后缀(这里不含前缀)的最大匹配值,即将对应匹配值的前缀与后缀对齐,例如这里已经匹配的部分为aba,母串后缀ba与模板串前缀ab最大匹配值为1,所以将模板串的a与母串的a对齐,即模板串的首位与母串的第三位对齐;

所以现在问题变为怎么求匹配值,即求next数组,不妨将模板串自身与自身比较,当产生一段匹配区间时,(例如串2的i~对应长度位置与串1的1~j已经一一对应,则next【串1当前的末位置】=j),所以next数组就求出来了。 匹配过程中模板串的移动还和上段思路一样。

用代码实现的话就是 

int next[11000];
void getNext()
{
    next[1]=0;//字符串数组从1开始;
    for(int i=2,j=0;i<=strlen(str);++i)
    {
        //j>0,出现第一个匹配的字符时才开始算法,否则说明除了两串相同外没有其他串1后缀与串2前缀匹配的部分
        while(j>0&&str[i]!=str[j+1])j=next[j];//某一位不对应,调整模板串的位置,只用到移动后对应完成时的后一位j;
        if(str[j+1]==str[i])j++;
        next[i]=j;
    }
}

同理,我们也可以得到模板串与母串匹配的代码;

int kmp[11000];
void KMP()
{
    //kmp[1]=0;两串完全相同也算一种情况,所以开头不再处理;
    for(int i=1,j=0;i<=n;++i)//n是母串长度;str母串,ptr模板串;
    {
        while(j>0&&str[i]!=ptr[j+1])j=next[j];
        if(str[i]==ptr[j+1])j++;
        kmp[i]=j;
       
       
       // 题型1:if(j==m)//m是模板串的长度,j==m说明母串中包含模板串,若秋第一次出现位置,返回i-m+1即可.求所有出现位置就只输出结果,不返回,继续下一层循环。
        //题型2:求出现次数,定义一个sum即可,继续下一层循环.
    }
}

 

针对问题的话:

目前看了的比如求模板串在母串中出现的位置,次数,这是最基础的模板题;

变式的话比如求多个串的最长公共子序列,这时枚举第一个串的子串,然后与其他串匹配即可,注意不要写成暴力,kmp这里没理解好的话是会TLE的,例如poj3450:http://poj.org/problem?id=3450

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值