KMP算法

KMP算法通常用来匹配字符串,时间复杂度为O(n+m)。一般来说,我们匹配字符串,首先想到的是对源字符的每个位置,都进行匹配。但这样花费的时间过多,时间复杂度为O(n*m),虽然在实际中,也可以接近O(n+m)。KMP算法采用了一个数组来保存元素的位置,这样就可减少匹配的次数(是不是和DP有些类似呢)

下面我们来说一下,它的实现思路,假设,有两个字符串源字符串R,目标字符串T,用来保存T中每个元素位置的数组next[],设匹配从R的第i个元素开始(我们以下标1表示第一个元素),第一次查看T的第j个元素(这里为第1个)是否与i相同,若相同j++,继续匹配。若不同,令j = next[ j ],然后继续匹配,直到j = 1。若还是不同,则令i++,j++,然后继续匹配,如此循环直到超出R或T的长度。

下面说一下它是如何减少匹配次数的,关键就在于next[],当我们发现有不匹配元素,不要急着将i的还原为匹配前的下一个,而是偷一下懒,先看一下T中是否有比当前j小,且与当前位置“等价”的位置,这里的意思是在T中存在着两段小数组t1,t2。t1与t2相等,且t1以T的第一个元素为开头,t2以“T的最后一个元素”为结尾(实际上以第j-1个元素结尾)。若存在t1,t2,则j = t1.length+1,即让t1后的第一个元素与R中的第i个元素进行比较。若相同,则比较下一元素,若不同,则再次进行此操作。这好像将T字符串,往前推(R不动),改为将R字符串往后推(T不动)。实际上,将T往后推,节省了大量的比较操作。而我们在next[]中存储的就是每个T元素的t1.length+1;这样当在第j个元素处不相同时,就可以直接从数组拿来使用。

下面我们再来说一下next[]的实现。首先,我们让它的长度为T.length+1,因为我们要以下标1表示第一个元素。并令next[1]=0;这样如果j==0,我们就知道T的元素到第一个了,应该让j=1,i++;进行下一个元素的匹配。

next[ j ] = k,{ k=Max(t1'.length,t1''.length) }。因为符合条件的t1可能有好多个,所以我们选那个长度最长的t1。

next[ j ]=1。若j之前的那段数组没有符合条件的,则令其为1。下面开始正式说明如何建立next[]

建立next[],其实也和比较两个字符串类似。我们可以设两个相同的T字符串,源字符串T1,匹配字符串T2,在开始时,使T2的第一个元素对应T1的第二个元素(否则没法比较,因为它们都相同).......(Talk is cheap ,show me the code --Linus)

/**
	 * 
	 * @param str 对str字符串建立next数组
	 * @param next
	 */
	private static void next(String str,int []next){
		
		next[1]=0;
		/*
		 * i指示T1的位置
		 * j指示T2的位置
		 * same表示i之前相同元素的最大个数,即相同小数组的最大长度(不包括i)
		 * 用same为next[]设值
		 */
		int i=2,j=1,len=next.length,same=0;
		char a=0,b=0;
		while(i


这样next[]就设置完成了,下面给出我的KMP算法:

private static int find(String pattern,String compile,int pos){
		int i=pos,j=1,len_pattern=pattern.length(),len_compile=compile.length();
		char a=0,b=0;
		while(i


你可能感兴趣的:(算法,数据结构)