kmp
作者:互联网
kmp:str1.indexOf(str2);
检查字符串2是1的子序列,并返回匹配的第一个字符位置
相比暴力匹配(时间复杂度O(N*M)),KMP通过nexts数组来加速匹配的过程,时间复杂度O(N)
next数组(建立的一个加速指标)
对str2,即要检查的字符串求next数组
nexts数组:i之前的字符串(和i本身无关)的前缀和后缀最大的匹配字符长度(不能取得整体,因为整体肯定是一样的,没有意义)
示例:nexts[]
a a x a a a a x a a x
0 1 2 3 4 5 6 7 8 9 10
-1 0 1 0 1 2 2 2 i
nexts[0]=-1 人为规定的
nexts[1]=0 不能取得整体所以是0
nexts[2]=1 a
nexts[3]=?怎么求?
看i-1位置的值是否等于y=next[i-1] y位置的值,
如果相等则nexts[i]=next[i-1]+1;
否则的话y=next[y]
当y=0时,则next[i]=0
加速匹配过程:
str1 a a b a a b k............
str2 a a b a a b a
i 0 1 2 3 4 5 6
next -1 0 3
nexts数组的用法:在遇到无法匹配的字符位置i(记为y)时,将str2[nexts[y]]=str1[i]
如果还是无法匹配时,将y重置为y=nexts[y] ->nexts[y],当nexts[y]=-1时,str2[0]==str1[i+1]
通过这种方式来加速匹配的过程
private static int getIndexOf(String str1,String str2){ if(str1==null||str2==null||str2.length()<1||str1.length()< str2.length()){ return -1; } int[] next=getNextArray(str2.toCharArray()); char[] ch1=str1.toCharArray(); char[] ch2=str2.toCharArray(); int x=0;//str1开始匹配的位置 int y=0;//str2开始匹配的位置 while (x<ch1.length&&y<ch2.length){//如果y越界,说明匹配成功,如果x越界,说明匹配结束了 if(ch1[x]==ch2[y]){ x++; y++; }else if(next[y]==-1){//y=0 //表示一通加速后,都没有匹配上,换个头重新开始匹配 x++; }else{ y=next[y]; } } return y==ch2.length?x-y:-1;//如果y的长度等于str.length说明匹配成功,匹配开始位置为x-y } private static int[] getNextArray(char[] ms){ //如长度为1 if(ms.length==1){ return new int[]{-1}; } //申请next数组 int[] next= new int[ms.length]; //o 位置为-1 人为规定 next[0]=-1; //1位置为0,因为都不能取整体 next[1]=0; //从位置2开始考虑 int i=2; int y=0;//当前是哪个字符和i-1在比较 //处理位置没有越界 // nexts[i]=?怎么求? // 看i-1位置的值是否等于y=next[i-1] y位置的值, // 如果相等则nexts[i]=next[i-1]+1; // 否则的话y=next[y] while (i<next.length){ if(ms[i-1]==ms[y]){ next[i++]=++y; }else if(y>0){ y=next[y]; }else { next[i++]=0; } } return next; }
标签:匹配,str2,str1,kmp,next,数组,nexts 来源: https://www.cnblogs.com/iwyc/p/15215904.html