串匹配算法之KMP算法

时间:2021-06-20 06:12:07

KMP算法简介就不讲了,对于朴素的模式串匹配算法,发生失配时每次只能移动一个位置,然后再进行比较,而KMP算法可以根据模式串本身的性质,来决定向后跳几步

下面我们用一个例子来说明

next数组的计算公式是

串匹配算法之KMP算法

串匹配算法之KMP算法


其实next数组还有一个简单的方法可以看出来

就是看它前面的与第0位开始的重复多少个,比如上面的 j=2的时候 next[1]=0,且p[j-1]=b!=p[0],所以next[j]=0;

当j=3时,其前面的为a==p[0]所以next[j]=1;

下面模拟下KMP算法的过程

第一趟 

串匹配算法之KMP算法

j=1的时候发生失配,next[j]=next[1]=0,所以要从p0重新开始匹配

第二趟

a c a b a a b a a b c a c a a b c
  a b a a b c a c                
j=0的时候发生失配,所以将目标串后移一位

第三趟

a c a b a a b a a b c a c a a b c
    a b a a b c a c              

j=5的时候发生失配,next[j]=next[5]=2,说明前面有两个是有p0p1重复的,目标串在这之前都是匹配的,所以说明目标串前面的两个也一定是与p0p1重复的,所以可以从p2匹配起

第四趟

a c a b a a b a a b c a c a a b c
          a b a a b c a c        

匹配成功。

下面提供一下产生next数组的代码

java版本的

public  static int[] makenext(String s){
int[] next=new int[s.length()];
next[0]=-1;
if(next[1]==next[0]) next[1]=1;
else next[1]=0;
for(int i=2;i<s.length();i++){
if(s.charAt(i-1)==s.charAt(next[i-1])) next[i]=next[i-1]+1;//这步是关键就是判断前面的一位是否满足重复序列
else {
if(s.charAt(i-1)==s.charAt(0)) next[i]=1;
else next[i]=0;
}
}
return next;
}

根据上面演示的KMP的过程,也可以得出下面的代码

public static void main(String[] args) {
// TODO Auto-generated method stub
String pattern="cacaa";
String target="acabaabaabcacaabc";
int[]next=makenext(pattern);
int i=0;
int j=0;
boolean  flag=false;
while(true) {
if(i>=target.length()) break;
if(j==pattern.length()) {
flag=true;
break;
}
if(target.charAt(i)==pattern.charAt(j)) {
i++;
j++;
} else {
if(j>0) {
j=next[j];
} else {
i++;
j=0;
}
}
}
if(flag) {
for(int k=0;k<pattern.length();k++)
System.out.print(target.charAt(k+i-j));

}
else System.out.println("没有匹配到");


}