KMP----总结
图文请参考:http://www.cnblogs.com/dolphin0520/archive/2011/08/24/2151846.html
以下是我的理解。
首先要理解next数组的存在意义:减少子串的回溯-》如何减少?
构建next数组:首先数组第一位next[0]=-1;为什么是-1,其实它只是一个标识,表示现在已经是next数组的首位了,其实next[0]<0即可。
先看代码(递推法):
1 void getNext(char stringArray[],int next[]) 2 { 3 next[0]=-1;//NEXT数组第一位设为-1; 4 int len=strlen(stringArray); 5 6 int i=0,index=-1; 7 //遍历子串得出NEXT数组 8 while(i<len) 9 { 10 //当子串没有任何匹配时或者当前字符与前缀字符相同 11 if(index==-1 ||stringArray[i]==stringArray[index]) 12 next[++i]=++index;//得出下一位字符串的权值 13 else 14 index=next[index];//失配时,前缀回到上一个前缀所保存的权值 15 } 16 17 //for(int i=0;i<len;i++) printf("%d ",next[i]);//输出next数组 18 }
首先要理解next数组的下一位的权值是由上一位权值所得出的。从代码可知:
可以构建next数组下一位的条件是当前前缀失配到-1,或者的当前字符与前缀表示的字符相同。而且当前缀是-1时,所构造的权值为0.
否则,就是失配,前缀会向前缀数组取权值index=next[index];
然后就是怎么使用next数组了,我对next数组的权值理解为失配的程度。
先看代码:
1 int KMPMatch(char string[],char subString[]) 2 { 3 int i=0,index=0,next[100]; 4 int len1=strlen(string),len2=strlen(subString); 5 6 getNext(subString,next);//得到Next数组 7 8 //遍历字符串 9 while(i<len1) 10 { 11 //当子串时第一个字符或者子串的index位置字符与字符串的i位置字符匹配时 12 if(index==-1 || string[i]==subString[index]) 13 { 14 i++;//字符串位置移动 15 index++;//子串位置移动 16 } 17 //否则向next数组取权值 18 else index=next[index]; 19 //当子串匹配完成时返回该位置 20 if(index==len2) return i-len2; 21 } 22 }
先看字符串能移动的条件:index=-1,也就是next数组首位时候,或者字符串的i位置的字符与子串index位置也就是失配位置(next的权值)相同
否则,也就是发生不匹配了,失配位置index=next[index]从next数组拿出失配程度