您的位置:首页 > 编程语言 > Java开发

java实现算法之KMP匹配算法(三个关键点掌握即可理解)

2017-03-13 11:38 405 查看
KMP算法在网上已经有很多详细解释的博客,这里我就不多解释其匹配过程了,只对我在学习KMP算法时遇到的一些关键点和难理解的地方做出解释。我觉得只要能看懂我要解释的这几点,kmp算法一定可以轻松的理解。

最好是先了解了什么是kmp匹配算法,和next数组时干什么的之后,再来看这篇文章,有助于你更好的理解,和更容易编写出kmp匹配算法。

首先我们要知道kmp算法,最关键的地方也是最难的地方就是next数组的构造过程,只要能把next数组的构造过程理解清楚,kmp算法基本就没有任何的难点了,下面我就只讲解next数组构造过程中需要注意和难理解的地方。

第一个关键点,就是next数组的构造过程实际上就是模式串自身匹配的过程,通过与自身匹配找到其与主串匹配时最小需要回溯的位置,其与自身匹配的过程实际上也是利用next数组的匹配。

第二个关键点,就是模式串与自身匹配,开始时指针是要相错一位的,其中一个指针i指向模式串第一位,另一个指针j指向模式串第一位的前一位也就是-1位,(-1位默认和任何字符匹配)这样好理解。

i

a b a a b c a c

   a b a a b c a c

j

条件有限,就是上面这种情况,可能现在你还没办法理解,等你看过关键点三,在回过头来看,可能会有更好的理解

第三个关键点,就是它是如何通过这种匹配过程来求出next数组的呢,下面我们在来看一种情况:

       i

a b a a b c a c

       a b a a b c a c

        j

当出现上述情况时,我们发现i指针和j指针指向的字符匹配了,这时候我们想,当用这个模式串和别的主串匹配时,当在i指针指向的下一个字符即i+1与主串不匹配时,是不是只要我们将模式串回溯到j指针指向的下一个位置即j+1就好了,因为此时我们知道,i和j是匹配的,我们只需要判断i+1和j+1是否匹配就好,也就是下面i和j指针指向的情况:

                         i

主串: a b a c a b a a b c

模串: a b a a b c a c

                          j

回溯:        a b a a b c a c

因此在求next数组时,当我们发现i指针和j指针匹配时,只需让i指针下一位的next数组等于j指针指向的下一位即可,也就是next[i+1]=j+1;

当i指针和j指针不匹配时,我们只需让j指针回溯至next[j]位置即可,然后利用next数组继续匹配即可构造出next数组。

下面是java具体实现代码

package KMPMatch;

import java.util.Arrays;
import java.util.Scanner;

public class Main {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
String s1=in.nextLine();
String s2=in.nextLine();
in.close();
System.out.println(kmpMatch(s1,s2));

}
public static int kmpMatch(String s1,String s2){
int []next=new int[s2.length()];
getNext(s2,next);
int n1=s1.length();
int n2=s2.length();
int i=0,j=0;

while(i<n1&&j<n2 ){
if(j==-1||s1.charAt(i)==s2.charAt(j)){
i++;
j++;
}else{
j=next[j];
//i=i-j+1;j=0;//简单的模式串匹配算法
}
}
if(j>=n2){//j>=n2实际上只能取到j=n2,表明模式串已经匹配完毕
return i-n2;
}else
return -1;

}

public static void getNext(String s,int []next){
int i=-1,j=0;//模式串与自身匹配时,相错一位
int n=s.length();
next[0]=-1;
while(j<n-1){//j这里为n-1是因为求next数组时是求相等的后一位的next值.
if(i==-1||s.charAt(i)==s.charAt(j)){//s.charAt在-1时报错,因此此时应添加条件跳过此情况
i++; j++;//先加加后匹配
next[j]=i;

}else{
i=next[i];
}
}
}

}
谢谢观看!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 算法 kmp 最易理解