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

回溯:

因此在求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];
			}
		}
	}

}

谢谢观看!