KMP详解

来源:互联网 发布:mac系统下gem安装sass 编辑:程序博客网 时间:2024/06/06 07:29

KMP算法又称看毛片算法,运用于字符串匹配问题
它的优秀性在于复杂度低而且不止能解决字符串相等的匹配问题
还可以根据题目的需要写个check函数解决一些另类的字符串问题
对于字符串匹配问题,最暴力的做法是这样的:
这里写图片描述
当匹配串A(蓝的)与待匹配串B(黑的)在如图棕色下标处(Aij+1Bj)匹配失败或匹配结束时
我们将匹配串的下标返回1,然后待匹配串的下标返回i+1
于是我们发现这样的算法很不优秀
这样一直讲下标i往回弹显然是不可取的
于是我们开始思考怎么让i不往回弹呢?
显然不将i往回弹时,我们需要知道一个最小的下标k
满足A[k,i1]B的前缀,
然而我们发现既然匹配到了i才失败,那么就表示A[i+j1,i1]==B[1,j1]
所以我们即需要知道一个最小的下标k,满足B[k,j1]==B[1,jk]
一般我们称这个kfailj
即当匹配串在下标j处匹配失败时,下标将会跳转到的位置
就不画图了,烦。。。。。
那么这个位置怎么求呢?
我们只需要用匹配串和匹配串自己匹配一次,每次找到一个最长的前缀等于当前后缀即可
当然这个时候也不能直接暴力判相等啊。。。
当判断[i,i+j1],[1,j]是否相等时,[i,i+j2],[1,j1]已经相等
所以只需判断[ij1,ij1],[j,j]是否相等即可,就得到的一个很好的优化
这使整个KMP复杂度有了更好的保证
模板:

void Get_KMP(int m){//匹配串造fail    fail[1]=0;fail[2]=1;    for(int i=2,j;i<=m;i++){        j=fail[i];        while(j&&B[i]!=B[j])j=fail[j];        fail[i+1]=j+1;    }}void match(int n,int m){//匹配待匹配串    for(int i=1,j=1;i<=n;i++){        while(j&&A[i]!=B[j])j=fail[j];        j++;        if(j==m+1){            //处理答案,看题目想干嘛        }    }}