码迷,mamicode.com
首页 > 编程语言 > 详细

字符串算法①——kmp

时间:2018-02-20 23:57:47      阅读:266      评论:0      收藏:0      [点我收藏+]

标签:位置   tps   接下来   定义   ++   就会   style   pos   int   

kmp算法是用来找A字符串的子串B的出现次数和位置的一种算法;

在看后面之前先看一个链接https://kb.cnblogs.com/page/176818/

然后对算法就有个大概的理解

 

为了实现这种算法我们需要一个next数组,也就是刚才链接里的部分匹配表,next[i]表示‘B中以i结尾的非前缀子串’与’B的前缀‘能够匹配的最长长度;

如:abababaac的i=7 为结尾的’非前缀子串‘有6个,分别是2~7,3~7,4~7,....,7~7;

如B【2~7】=’bababa‘与前缀’ababab‘不匹配

   B【 3~7】=‘ababa’与前缀‘ababa‘匹配,长度为5;

.............

得出next【7】=5;

但如何求出next数组我们可以假设next【1~6】已经被求出。next【6】=4;及B【3~6】与B【1~4】匹配;

接下来,B【7】=B【5】=’a‘,所以B【7】=5;皆大欢喜,下一个匹配了;

但当next【8】时,B【8】=‘a‘   B【6】=’b‘不匹配;

所以我们只好把匹配长度缩短;就是说上面我们以i=7接韦德匹配长度出了5之外,还有B[5~7]于B【1~3】的长度为3的匹配;B【1】于B【7】的长度为1的匹配;

我们尝试这两种匹配能否使i=8时匹配;

但B【8】于B【4】,B【2】不相等,所以我们只能让i=8冲头开始匹配,B【1】恰好于B【8】匹配;所以next【8】=1;

单我们是如何记路5,3,1这些匹配长度的?

首先next【7】=5;说明从i=7往前5个字符于B【1~5】是相等的。

这是我们定义一个j;使从5往前j个字符与B【1~j】匹配;什么意思,就是以5为next【5】;(别忘了next数组定义);

当j=next【5】=3之后,下一个要找的就是next【3】;

所以代码就有了(可能还没有,看看代码就会了)

1.初始化next【1】=j=0,假设next【1~i-1】都求出,正在求next【i】。
2.尝试匹配下一位,若果匹配失败,就令j=next【j】(上面讲了为什么)。直到j=03.若果匹配,就令j+1,next【i】=j;

next[1]=0;
for(int i=2,j=0;i<=strlen(a);++i)
{
    while(j>0 && a[i]!=a[j+1]) j=next[j]; ////匹配失败
    if(a[i]==a[j+1]) j++;      /// 匹配成功
    next[i]=j;
}

然后有了next数组就可以kmp了

for(int i=1,j=0;i<=strlen(b);++i)
{
    while(j>0 && (j==n || b[i]!=a[j+1])) j=next[j];
    if(b[i]==a[j+1]) j++;
    if(j==strlen(a)) ///此时匹配  位置为i-strlen(a)+1
}

然后就没了;

字符串算法①——kmp

标签:位置   tps   接下来   定义   ++   就会   style   pos   int   

原文地址:https://www.cnblogs.com/AidenPearce/p/8456005.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!